【二进制与位运算】C. Array Elimination

题目来源:

Problem - C - CodeforcesCodeforces. Programming competitions and contests, programming communityhttps://codeforces.com/contest/1602/problem/C

题干:

 按位与运算的定义:

 算法解释:

 官方思维:

 解析:

感谢这篇文章对于英文解释的翻译和总结:

Codeforces-1601A: Array Elimination_Sherlock_Holmewei的博客-CSDN博客Codeforces-1601A: Array Elimination题目大意题目解析这道题应该考虑对于每一个元素 $c$https://blog.csdn.net/Sherlock_Holmewei/article/details/120964476?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163532473216780357255921%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163532473216780357255921&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-120964476.first_rank_v2_pc_rank_v29&utm_term=Array+Elimination&spm=1018.2226.3001.4187对于数组中的每个a[j],换算成二进制,假设在一次操作中一个a[j]的二进制bit位 从1变为0

(即进行了模二减运算,减去那个按位与运算得到的操作数)

这个变化一定伴随着其他k-1个在 i-th bit 的变化

(因为如果想执行bit位从1->0的运算,先保证操作数的 i-th bit一定是1。即位运算的时候这个位置上所有的a[j]^{i}都一定是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));//这里的右移运算符,二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
//按位与运算符判断当前位是否为1
        }
        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

Guess you like

Origin blog.csdn.net/nathanqian123/article/details/120994398