CF1602C Array Elimination

CF传送门

思路:我们将\(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;
}
posted @ 2021-12-14 16:34  Wraith-Fiee  阅读(30)  评论(0)    收藏  举报