题目大意:对于一个数组,每次选择k个数,求出k个数的AND之和x,并将这k个数都减去x,最后使得整个数列的数全为0。问存在多少个这样的k并将k升序输出。
题解:首先分别求出每一位上的1的数量,由于一次性取出k个数,所以每一位上1的数量必定是k的倍数,否则将会有数在这一位上无法变成0。那么k就是各位1的数量的公约数。先求出各位的最大公约数,最大公约数的所有约数即为答案。
注意特判数组本身全为0的情况!
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[32];
int gcd(int a, int b)
{
if (a < b)swap(a, b);
if (a % b == 0)return b;
else return gcd(b, a % b);
}
void solve()
{
int n,x,res=0;
cin >> n;
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++)
{
cin >> x;
for (int j = 0; j <= 30; j++)
{
if ((x >> j) & 1)a[j]++;
}
}
sort(a, a + 30);
res = a[29];
for (int i = 28; i >= 0; i--)
{
if (a[i] > 0)res = gcd(res, a[i]);
}
if (res == 0)
{
for (int i = 1; i <= n; i++)
cout << i << " ";
}
else
{
for (int i = 1; i <= res; i++)
{
if (res % i == 0)cout << i << " ";
}
}
cout << endl;
}
int main()
{
int t;
cin >> t;
while (t--)
{
solve();
}
}