A
题意:A,B,C三个人分别有硬币a,b,c枚,D有n枚硬币要全部分给A,B,C三人,问是否存在分配方案使最终A,B,C三人硬币数相等。
我的思路:算出每人距离三人中的最大值 差多少,先从n里面拿一些硬币把这个差距补平,然后看剩下的硬币数能不能整除3。
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int a,b,c,n;
cin>>a>>b>>c>>n;
int maxn=max({a,b,c});
int p=maxn-a+maxn-b+maxn-c;
if(p<=n&&(n-p)%3==0) puts("YES");
else puts("NO");
}
}
B
题意:给出n个包裹的位置(x,y),机器人从(0,0)出发,只能向右或向上,问是否存在一种走法能访问到所有的包裹,向右是'R',向上是'U',输出字典序最小的走法。
我的分析:对n个包裹排序(以x为第一关键字,y为第二关键字(这样其实用pair就可以)),这样如果某个排在前面的包裹,却在后面的包裹的右下方(应该在右上),就是没法走的情况,flag=false。
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
struct node{
int x,y;
bool operator < (const node& t)const{
if(x==t.x) return y<t.y;
return x<t.x;
}
}a[N];
int main(){
int t;
cin>>t;
while(t--){
int n;
cin>>n;
char ans[2005];
int cnt=0;
for(int i=1;i<=n;++i) cin>>a[i].x>>a[i].y;
sort(a+1,a+1+n);
bool flag=true;
for(int i=1;i<=n;++i){
if(a[i].y<a[i-1].y) {flag=false;break;}
else{
for(int j=0;j<a[i].x-a[i-1].x;++j) ans[cnt++]='R';
for(int j=0;j<a[i].y-a[i-1].y;++j) ans[cnt++]='U';
}
}
if(flag){
puts("YES");
ans[cnt]=0;
puts(ans);
}else{
puts("NO");
}
}
}
注意:char ans[cnt]=0,才可cout<<ans;否则会输出奇怪的字符。
C.
题意:给出n,问n能否拆成三个不同的数a,b,c的乘积,a,b,c>2,可以的话输出a,b,c.
我的思路:对n分解质因数,如果某个质因数的个数到达6(比如6个2)或者能分解出3个不同的质因数或者能分解出两个不同的质因数且这两个质因数的总个数到达4,那么yes,否则no。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
while (n--){
int x;
cin >> x;
int cnt=0;
int xx=x;
bool flag=false;
int a[105],b[105];
memset(a,0,sizeof a);
memset(b,0,sizeof b);
for (int i = 2; i <= x / i &&!flag; i ++ )
if (x % i == 0){
++cnt;
int s = 0;
while (x % i == 0) x /= i, s ++ ;
a[cnt]=i;
b[cnt]=s;
if(cnt>=3||b[cnt]>=6||cnt>=2&&b[cnt]+b[cnt-1]>=4){
flag=true;
break;
}
}
if(x>1) {++cnt;a[cnt]=x;b[cnt]=1;}
if(cnt>=3||b[cnt]>=6||cnt>=2&&b[cnt]+b[cnt-1]>=4){flag=true;}
if(flag){
puts("YES");
if(b[cnt]>=6) cout<<a[cnt]<<" "<<a[cnt]*a[cnt]<<" "<<xx/(a[cnt]*a[cnt]*a[cnt])<<endl;
else cout<<a[cnt]<<" "<<a[cnt-1]<<" "<<xx/(a[cnt]*a[cnt-1])<<endl;
}else{
puts("NO");
}
}
return 0;
}
//思路秒出,实现浪费了很多时间
D.初始数组为空,给出n和k,有n次询问,每次给出a_i,加(append)在数组里,每次加完数后,可以进行这样的操作:对当前数组中任意的数加上或减去任意次k,使该数组的MEX(最小非负整数)最大,输出这个最大的MEX,在下一次询问前,所有操作清空。
思路:可以发现每次的答案是单调递增的,然后模拟。。。我暂时讲不清楚
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+5;
int a[N];
int main(){
int n,k;
scanf("%d%d",&n,&k);
int now=0;
while(n--){
int x;
scanf("%d",&x);
++a[x%k];
while(a[now%k]){
--a[now%k];
++now;
}
printf("%d\n",now);
}
return 0;
}