「DAOI R1」Magic 题解
来自出题人的题解。
这道题我们采用分类讨论的思想。
n\le2 :
当
当
if(n==1) puts("YES");
if(n==2){
if(a[1]==0 || a[2]==0) puts("YES");
else puts("NO");
}
n=3 :
我们可以将这个数列表示为
首先将这个数列升序排序。
那么就可以将三个数变成
具体过程:
将
假如剩下的数为
我们将
再将
由此在不改变
-
如果
x\bmod3 为0 ,则最后肯定可以使x 变成0 ,并把y 变成x+y 。 -
如果
x\bmod3 不为0 ,那么肯定可以使用刚才的方式将原数列变为:
这里的
或者
当数列是
这时,若
当数列是
这时,若
上面两种方法一个满足
所以当满足上述条件之一是时一定可以实现,否则不行。
注意:
if(n==3){
sort(a+1,a+n+1);
a[3]+=a[1]*2; a[2]-=a[1]; a[1]=0;
if(a[2]%3==0 || a[3]%3==0) puts("YES");
else if((a[2]%3==1 && a[3]%3==1) || (a[3]%3==1 && a[2]%3==1)) puts("YES");
else if((a[2]%3==2 && a[3]%3==2) || (a[3]%3==2 && a[2]%3==2)) puts("YES");
else puts("NO");
}
n=4 :
对于这种情况,我们可以用类似于
具体方法:先对整个序列进行升序排序,然后对于每一个
转换完后,我们可以先将
然后我们再将两个
所以我们可以在不改变前面两个
由于我们在
-
当
x\bmod2 为0 时,直接进行\dfrac{x}{2} 次减2 操作。 -
当
x\bmod2 为1 时,先进行一次减3 操作,再进行\dfrac{n-3}{2} 次减2 操作。
按照以上的推论,当
同样的,如果我们要进行减
综上,当原数列排序后不为
n>4 :
当
其实我们没必要排序,只用统计
if(n>=4){
int cnt0=0,cnt1=0,cnt2=0;
for(int i=1;i<=n;i++){
if(a[i]==0) cnt0++;
else if(a[i]==1) cnt1++;
else if(a[i]==2) cnt2++;
}
if(cnt0==n-2 && cnt1==1 && cnt2==1) puts("NO");
else puts("YES");
}
Code:
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,a[maxn];
int main(){
int T; scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",a+i);
if(n==1) puts("YES");
if(n==2){
if(a[1]==0 || a[2]==0) puts("YES");
else puts("NO");
}
if(n==3){
sort(a+1,a+n+1);
a[3]+=a[1]*2; a[2]-=a[1]; a[1]=0;
if(a[2]%3==0 || a[3]%3==0) puts("YES");
else if((a[2]%3==1 && a[3]%3==1) || (a[3]%3==1 && a[2]%3==1)) puts("YES");
else if((a[2]%3==2 && a[3]%3==2) || (a[3]%3==2 && a[2]%3==2)) puts("YES");
else puts("NO");
}
if(n>=4){
int cnt0=0,cnt1=0,cnt2=0;
for(int i=1;i<=n;i++){
if(a[i]==0) cnt0++;
else if(a[i]==1) cnt1++;
else if(a[i]==2) cnt2++;
}
if(cnt0==n-2 && cnt1==1 && cnt2==1) puts("NO");
else puts("YES");
}
}
getchar(); getchar();
return 0;
}