Array Elimination &运算,gcd,思维

在这里插入图片描述

题意 :

  • 给一序列,每次可选择k个数,让它们都减去它们的gcd,要在任意次数后这个序列变为全0,输出所有可能的k

思路 :

  • 考虑&运算的性质,必然是每次选择k个相同的数,才能让这k个数全0,因此k是n的因数
  • 类似地,从二进制每位的角度,k必须是每i位上1的个数的因数
  • 因此,我们统计每位上1的个数的gcd,然后输出这个gcd的所有因数即可
  • 特别地,当所有元素都为0时,直接输出1~n
  • 0和任何数的gcd都是那个数,所以0作为起点,且在统计gcd时多统计最高位也没有影响
#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 35;

int a[N];

int gcd(int a, int b)
{
    
    
    return b ? gcd(b, a % b) : a;
}

int main()
{
    
    
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

    int _;
    cin >> _;

    while (_ -- )
    {
    
    
        memset(a, 0, sizeof a);
        int n;
        cin >> n;
        for (int i = 1; i <= n; i ++ )
        {
    
    
            int x;
            cin >> x;
            for (int j = 0; j < 30; j ++ )
                a[j] += (x >> j & 1);
        }

        int div = 0;
        for (int i = 0; i < 30; i ++ ) div = gcd(div, a[i]);

        if (div == 0)
        {
    
    
            for (int i = 1; i <= n; i ++ ) cout << i << ' ';
            cout << endl;
            continue;
        }

        for (int i = 1; i <= div; i ++ )
            if (div % i == 0)
                cout << i << ' ';
        cout << endl;
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_51448653/article/details/121222195