【二进制与位运算】C. Array Elimination
作者:互联网
题目来源:
题干:
按位与运算的定义:
算法解释:
官方思维:
解析:
感谢这篇文章对于英文解释的翻译和总结:
(即进行了模二减运算,减去那个按位与运算得到的操作数)
这个变化一定伴随着其他k-1个在 i-th bit 的变化
(因为如果想执行bit位从1->0的运算,先保证操作数的 i-th bit一定是1。即位运算的时候这个位置上所有的都一定是1,需要被清除为0)
所以最终在每一次操作中操作数对于每一个i-th清除必然有k个i-th bit位被清除
这样可以总结出每执行一次操作数清除,对于每一需要清除的 i-th bit位,必然有k个a[j](数组元素)要被清除,这样一来k即是i-th bit位上值为1的元素个数的约数,从而得到一个结论
数组能够消为全0⇒k是所有bit位为1的数字个数的公约数
我们可以开辟一个数组g,存入g1,g2,g3...gn(gi代表二进制第i位上值为1的数组a[j]元素的个数)
我们只要求出这个数组所有元素的最大公约数gcd,再列举出gcd的所有约数,就是该题的答案!
附上他人的ac源代码:
#include <bits/stdc++.h>
using namespace std;
int bits[32];
int gcd(int a, int b)
{ return b == 0? a: gcd(b, a % b);}//欧几里得算法
int main()
{
int n, t;
cin >> t;
while(t--)
{
cin >> n;
memset(bits, 0, sizeof(bits));
for(int i = 0; i < n; ++i)
{
cin >> a[i];
for(int j = 0; j < 31; ++j)
bits[j] += (1 & (a[i] >> j));
}
int k = bits[0];
for(int j = 0; j <= 31; ++j) k = gcd(k, bits[j]);
if (k == 0)
{
for (int i = 1; i <= n; ++i) cout << i << " ";
} else
{
for (int i = 1; i <= k; ++i)
if (k % i == 0) cout << i << " ";
}
cout << endl;
}
return 0;
}
————————————————
版权声明:本文为CSDN博主「盖乌咪·A·埃迪尔」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Sherlock_Holmewei/article/details/120964476
标签:数组,二进制,int,th,Elimination,Array,bits,bit,运算 来源: https://blog.csdn.net/nathanqian123/article/details/120994398