CF1602C Array Elimination
思路:我们将\(a_1\),\(a_2\)......\(a_n\)每个数都写成二进制数,我们要将每个\(a_i\)最终消为0,即每个数的二进制位为1的最终都消为0,因为二进制每一位都互不影响,因此我们把这n个数右对齐之后,单独来看每一列
我们来看样例13、7、25、19
13:01101
07:00111
25:11001
19:10011
从右往左看,第一列4个全为1,1&1=1,因此当1&1&1&1时(k=4),符合条件,1&1&1时(k=3),计算之后四个1会变成3个1和1个0就不能达到全部消0的要求,1&1时(k=2),计算之后变为2个1和2个0,再通过1&1即可全消0,之后每一列都这样想,即可发现,当我们计\(ans_i\)为第\(i\)列的1的个数,那么当\(k\)等于\(ans_i\)的因数时,就能将这一列的1全消为0,那么将这些列综合起来看,就是满足这\(ans_i\)的\(gcd\)的因数时都可全消为0
\(PS\):当这\(n\)个数均为0时,\(k\)可取1~\(n\)中任意数
Code:
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
inline int gcd(int a,int b) {
return b>0 ? gcd(b,a%b):a;
}
int t,n,a[N];
int ans[N];
int main(){
cin>>t;
while(t--){
memset(ans,0,sizeof(ans));
cin>>n;
int maxn=0;
int flag=0;
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]!=0) flag=1;
}
for(int i=1;i<=n;i++) {
int cnt=1;
for(;a[i];a[i]>>=1){
if(a[i]&1) ans[cnt]++;
cnt++;
}
maxn=max(maxn,cnt);
}
int tt=ans[1];
for(int i=2;i<=maxn;i++){
tt=gcd(tt,ans[i]);
}
if(tt==1&&flag==1) cout<<1<<endl;
else if(flag==0) {
for(int i=1;i<=n;i++) cout<<i<<" ";
cout<<endl;
}
else if(tt!=1&&flag==1){
for(int i=1;i<=tt;i++){
if(tt%i==0) cout<<i<<" ";
}
cout<<endl;
}
}
return 0;
}