这题是大一暑假时候做的,当时没有出,直到今天突然觉得应该把没过的题目再做一边,不然真的是越积越多。
现在能够独立做出来真的是难以表达的兴奋,刚开始的时候就觉得 O(30 * 30 * n)的复杂度有点不安全,不过还是敲了,事实说明实际的负责度没这么高。和去年一样,没有思路,后来仔细一想,真的是数学题。现在感觉爱上了Math...
附上代码:
1 #include2 #include 3 4 // 保存原始数组 5 int b[100005]; 6 // a[i][j]表示b[i]的二进制表示法中的各个位上的数值, 而able数组保存的是每一轮中可以选的标记 7 bool a[100005][32], able[100005]; 8 int n; 9 10 int main(void) {11 while (~scanf("%d", &n) && n) {12 memset(a, false, sizeof(a));13 for (int i = 0; i < n; i++) {14 int x;15 scanf("%d", &x);16 b[i] = x;17 for (int j = 30; j >= 0; j--) {18 if ((1 << j) & x)19 a[i][30-j] = true;20 }21 }22 23 int cnt;24 for (int i = 0; i <= 30; i++) {25 cnt = 0;26 memset(able, false, sizeof(able));27 for (int j = 0; j < n; j++) {28 if ( a[j][i] ) {29 able[j] = true;30 cnt++;31 }32 }33 if (cnt == 0) continue;34 35 int j;36 for (j = i + 1; j <= 30; j++) {37 int f = 0;38 for (int k = 0; k < n; k++) {39 if ( able[k] ) {40 if ( !a[k][j] ) {41 f = 1;42 break;43 }44 }45 }46 if (f == 0)47 break;48 }49 if (j > 30)50 break;51 }52 printf("%d\n", cnt);53 int flag = 0;54 for (int i = 0; i < n; i++) {55 if ( able[i] ) {56 if (flag) 57 printf(" ");58 flag = 1;59 printf("%d", b[i]);60 }61 }62 puts("");63 }64 65 return 0;66 }