https://codeforces.com/problemset/problem/1372/A
题意:
题目给出一个数n,要求输出一个n长度的数组(范围[1,1000]),对于数组中任意的x,y,z,有x + y != z,数组元素可以重复。
思路:
很简单,数组元素都相同即可。
代码:
#include
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int t,n;
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<n;i++){
printf("%s%d",i==0?"":" ",1);
}
printf("\n");
}
return 0;
}
https://codeforces.com/problemset/problem/1372/B
题意:
给出一个数n,求两个数a和b,使得a+b=n且LCM(a,b)(就是a和b的最小公倍数)最小。
思路:
当n是偶数时,必然a和b都等于n/2
当n是奇数且是素数时,a和b分别是1和n-1
当n是奇数且不是素数时,a和b分别是n/x,n-n/x,这里的x是n的最小质因数
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int t,n;
int tmp;//记录非质数的奇数最小的因数
bool judge(int x){//判断素数
if(x==1) return false;
if(x==2) return true;
for(int i=2;i<=(int)sqrt(x);i++){
if(x%i==0){
tmp=i;
return false;
}
}
return true;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
if(n%2==0){//若n是偶数,就是n/2
printf("%d %d\n",n/2,n/2);
}else{
if(judge(n)){//如果n是奇数而且是素数
printf("%d %d\n",1,n-1);
}else{//如果n是奇数而且不是素数
printf("%d %d\n",n/tmp,n-n/tmp);
}
}
}
return 0;
}
https://codeforces.com/problemset/problem/1372/C
题意:
给出一个大小为 n的排列,每次操作可以选取一个连续子数组任意排列其中的元素,要求每个元素的位置必须与操作前不同,问将排列排为1-n的顺序至少需要操作多少次。
思路:
(1)已经排好了,0次操作。
(2)只有一段连续区间都不在自己的位置,1次操作。
(3)其他的情况两次操作。
证明:
两次都操作整个数组。
第一次:选取整个数组,将所有ai = i
的视为一体,在这个整体中每个元素循环右移一位,将余下 ai != i
的元素各自归位后也视为一体,在这个整体中的每个元素也循环右移一位。
第二次:选取整个数组,将第一次的两个整体中的元素各自循环左移一位。
比如题目给的3 2 4 5 1 6 7
第一次:2 6 7在正确的位置,所以将2 6 7变为 7 2 6
3 4 5 1不在正确的位置,所以将3 4 5 1归位变为1 3 4 5
此时数组变为1 7 3 4 5 2 6
因为要进行第二次操作,所以继续把1 3 4 5右移一位,数组变为5 7 1 3 4 2 6
第二次:两个整体都在各自里面左移一位。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 200005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int t,n;
int a[MAX];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int cnt=0;
bool flag=false;
for(int i=1;i<=n;i++){
if(a[i]!=i&&!flag) flag=true,cnt++;
else if(a[i]==i) flag=false;
}
if(!cnt) printf("0\n");
else if(cnt==1) printf("1\n");
else printf("2\n");
}
return 0;
}
https://codeforces.com/problemset/problem/1372/D
题意:
给出n个数,可以将一个位置相邻的两个数求和,然后把当前位置的数替换为这两个数的和。不断操作直到剩下一个数,求这个数的最大值。
思路:
总共需要删除int(n / 2)个数,然后对剩下的数求和,且每次选择的位置不相邻。分别利用b和c数组求得(不相邻的)前缀和及(不相邻的)后缀和。
代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX 200005
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n;
ll a[MAX],b[MAX],c[MAX];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lld",&a[i]);
}
for(int i=0;i<n;i++){
if(i<2) b[i]=a[i];
else b[i]=b[i-2]+a[i];
}
for(int i=n-1;i>=0;i--){
if(i>n-3) c[i]=a[i];
else c[i]=c[i+2]+a[i];
}
ll ans=b[0];
for(int i=0;i<n;i++){
ans=max(ans,b[i]+c[i+1]);
}
printf("%lld",ans);
return 0;
}