Finding OR Sum
题目大意
有两个非负整数 \(x\) 和 \(y\) ,不知道具体数值,但是有两次机会
输入一个\(n\),会返回 \((n|x)+(n|y)\),两次过后,要输出 \(!\),并且会输入一个 \(m\),你要输出 \((m|x)+(m|y)\)
思路
由于只有两次机会,所以可以考虑分别得出 x 和 y 奇数位和偶数位的性质
-
第一次输入的n考虑奇数位的性质,所以它的偶数位需要都为1,这样才能体现x和y偶数位的性质
-
同理,第二次输入的n考虑偶数位的性质,所以它的奇数位需要都为1
该如何得出性质 ?
首先要清除返回的数据中ji或者ou对它的影响
以奇数位为例
因为返回的是 \((n+x)|(n+y)\) ,所以需要 h -= ji + ji;清除影响
-
如果返回的数据的偶数位为1,说明这个后一位的奇数位x和y都是1
- b010 和 b010 得到的就是 b100
-
如果返回的数据的奇数位为1,说明这一位上一个为0,一个为1
- b010 和 b000 得到的就是 b010
-
如果返回的数据奇数位为1, 说明这一位上都为0
- b100 和 b000 得到的就是 b100
偶数位同理
这样就能推断出x和y的每一位情况,最后直接与m或再相加就能得到答案
代码
// Problem: E. Finding OR Sum
// Contest: Codeforces - Codeforces Round 1008 (Div. 2)
// URL: https://codeforces.com/contest/2078/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <iostream>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <stack>
#include <queue>
#include <unordered_map>
#include <map>
#include <vector>
#include <cstring>
#include <bitset>
#include <set>using namespace std;
using ll = long long;
int ji, ou;int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
int lcm(int a, int b) {return a / gcd(a, b) * b;}void solve()
{int x = 0, y = 0, h = 0;//奇数位cout << ji << endl;cin >> h;h -= ji + ji; //得到x和y在奇数位的具体数值,去掉ji的影响for(int i = 0; i < 31; i++) {if(h & (1 << i)) {if(i & 1) x |= (1 << i); //将x的第i位设为1else {x |= (1 << (i - 1)); //h在偶数位上为1,则是x和y的i-1位都为1y |= (1 << (i - 1));}}}//偶数位cout << ou << endl;cin >> h;h -= ou + ou;for(int i = 0; i < 31; i++) {if(h & (1 << i)) {if(i & 1) {x |= (1 << (i - 1));y |= (1 << (i - 1));}else x |= (1 << i);}}cout << '!' << endl;int m; cin >> m;cout << (m | x) + (m | y) << endl;
}int main()
{ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);int t; cin >> t;//int t = 1;for(int i = 0; i < 30; i++) {if(i & 1) ou |= (1 << i); //奇数位都是1,用来确定偶数位else ji |= (1 << i); //偶数位都是1,用来确定奇数位}while (t--) solve();
}