题意:
输入q,然后输入q个a,对于每个a,找到一个b,使gcd(a ^ b, a & b)最大,输出这个最大的gcd;
思路:
用k表示a二进制最高位的二进制编号,1,2,4,8对应1,2,3,4;
假如a不是 (1 << k) - 1这种形式的,那么总能找到一个b使a ^ b == (1 << k) - 1,而a & b == 0,这个时候gcd一定最大。如果a是 (1 << k) - 1,那么因为b不能为0,所以凑不出 (1 << k) - 1,没办法只能暴力了,因为(1 << k) - 1这样的形式的a也只有24个,所以我们要事先打表,否则应该会超时
打表代码:
#include "bits/stdc++.h" using namespace std; int main() { for (int i = 3; i <= (1 << 25) - 1; i = i << 1 | 1) { int max_gcd = 0; for (int j = 1; j < i; j++) { max_gcd = max(max_gcd, __gcd(i ^ j, i & j)); } printf("mp[%d] = %d;\n", i, max_gcd); } return 0; }
提交代码:
C - Meaningless Operations | GNU C++11 | Accepted | 30 ms | 0 KB |
#include "bits/stdc++.h" using namespace std; map<int, int> mp; int main() { mp[3] = 1; mp[7] = 1; mp[15] = 5; mp[31] = 1; mp[63] = 21; mp[127] = 1; mp[255] = 85; mp[511] = 73; mp[1023] = 341; mp[2047] = 89; mp[4095] = 1365; mp[8191] = 1; mp[16383] = 5461; mp[32767] = 4681; mp[65535] = 21845; mp[131071] = 1; mp[262143] = 87381; mp[524287] = 1; mp[1048575] = 349525; mp[2097151] = 299593; mp[4194303] = 1398101; mp[8388607] = 178481; mp[16777215] = 5592405; mp[33554431] = 1082401; int t, n; scanf("%d", &t); while (t--) { scanf("%d", &n); if (mp.count(n)) { printf("%d\n", mp[n]); continue; } int k = 0; while (n) { k++; n >>= 1; } printf("%d\n", (1 << k) - 1); } return 0; }
这次比赛得到的教训是打表程序跑出来的结果一定要是可以直接复制粘贴的,比赛的时候前面的题本来就做的不够快,然后当时打表程序不够好,这题还手敲了switch,结果来不及提交了。还是map好,没有引号百分号,用printf输出比较方便。