Finding OR Sum

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位设为1
    		else {
    			x |= (1 << (i - 1)); //h在偶数位上为1,则是x和y的i-1位都为1
    			y |= (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();
}
posted @ 2025-03-13 00:56  PeachyGalaxy  阅读(29)  评论(0)    收藏  举报