这题是大一暑假时候做的,当时没有出,直到今天突然觉得应该把没过的题目再做一边,不然真的是越积越多。
现在能够独立做出来真的是难以表达的兴奋,刚开始的时候就觉得 O(30 * 30 * n)的复杂度有点不安全,不过还是敲了,事实说明实际的负责度没这么高。和去年一样,没有思路,后来仔细一想,真的是数学题。现在感觉爱上了Math...
附上代码:
#include <cstdio>
#include <cstring>
// 保存原始数组
int b[100005];
// a[i][j]表示b[i]的二进制表示法中的各个位上的数值, 而able数组保存的是每一轮中可以选的标记
bool a[100005][32], able[100005];
int n;
int main(void) {
while (~scanf("%d", &n) && n) {
memset(a, false, sizeof(a));
for (int i = 0; i < n; i++) {
int x;
scanf("%d", &x);
b[i] = x;
for (int j = 30; j >= 0; j--) {
if ((1 << j) & x)
a[i][30-j] = true;
}
}
int cnt;
for (int i = 0; i <= 30; i++) {
cnt = 0;
memset(able, false, sizeof(able));
for (int j = 0; j < n; j++) {
if ( a[j][i] ) {
able[j] = true;
cnt++;
}
}
if (cnt == 0) continue;
int j;
for (j = i + 1; j <= 30; j++) {
int f = 0;
for (int k = 0; k < n; k++) {
if ( able[k] ) {
if ( !a[k][j] ) {
f = 1;
break;
}
}
}
if (f == 0)
break;
}
if (j > 30)
break;
}
printf("%d\n", cnt);
int flag = 0;
for (int i = 0; i < n; i++) {
if ( able[i] ) {
if (flag)
printf(" ");
flag = 1;
printf("%d", b[i]);
}
}
puts("");
}
return 0;
}