「杂题乱刷2」CF2036G

这题 *2400 纯唐吧,感觉 *1800 差不多。

题目链接

CF2036G Library of Magic(*2400)

解题思路

注:\(\oplus\) 表示异或运算。

首先我们想一个通解,就是先二分出第一个数和第三个数,然后第二个数就是所有数的异或和异或上这两个数,操作次数为 \(2 \times \log n + 1\),可以通过。

但是有个情况特别难受,就是可能会出现中间有数字但是询问结果为 \(0\) 的情况。

考虑何时会出现这种情况。

由于题目里保证删的数字不同,因此显然查询结果为 \(0\) 时这个区间中只含 \(0\)\(3\) 个数字。

于是我们先判断是否有 \(ans1 \oplus ans2 \oplus ans3 = 0\),若不是,我们可以直接套用上述二分的做法。

否则,由于这三个数的异或和为 \(0\),因此我们可以找到含有最高二进制位的两个数字,那么此时我们可以二分出这两个数字中的其中一个数字,另一个数字可以通过这两个数的异或和异或查询出来的数确定,剩下一个数可以通过所有数的异或和异或这两个数字的异或和确定。

操作次数 \(2 \times \log n + 1\),可以通过。

参考代码

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define forl(i,a,b) for(re ll (i)=(a);i<=(b);(i)++)
#define forr(i,a,b) for(re ll (i)=(a);i>=(b);(i)--)
#define QwQ return 0;
ll _t_;
void _clear(){}
ll n;
ll ans[10];
ll get(ll x,ll y)
{
	ll S=0;
	forl(i,1,3)
		if(x<=ans[i] && ans[i]<=y)
			S^=ans[i];
	return S;
}
ll ask(ll x,ll y)
{
	if(x>n)
		return 0;
	Min(y,n);
	cout<<"xor "<<x<<' '<<y<<endl;
	ll z;
	cin>>z;
//	z=get(x,y);
	return z;
}
void print(ll x,ll y,ll z){
	cout<<"ans "<<x<<' '<<y<<' '<<z<<endl;
}
ll pw(ll x){
	return 1ll<<x;
}
void solve()
{
    _clear();
	cin>>n;
	ans[1]=1;
	ans[2]=2;
	ans[3]=3;
	if(n==3)
	{
		print(1,2,3);
		return ;
	}
	if(ask(1,n)==0)
	{
//		cout<<"AWaDa!\n";
		forr(i,61,0)
		{
			ll num=ask(pw(i),pw(i+1)-1);
			if(num!=0 && !(num&pw(i)))
			{
		//		cout<<i<<endl;
				ll L=pw(i),R=pw(i+1)-1;
				while(L<R)
				{
					ll Mid=(L+R)/2;
					ll num=ask(pw(i),Mid);
					if(num==0)
						L=Mid+1;
					else if(ask(pw(i),Mid)&pw(i))
						R=Mid;
					else
						R=Mid;
				}
				ll _1=L,_2=num^L,_3=_1^_2;
				print(_1,_2,_3);
				return ;
			}
		}
		exit(-1);
	}
	else
	{
		ll all=ask(1,n);
		ll _1=0,_2=0,_3=0;
		ll L=1,R=n;
		while(L<R)
		{
			ll Mid=(L+R)/2;
			if(ask(1,Mid)==0)
				L=Mid+1;
			else
				R=Mid;
		}
		_1=L;
		L=1,R=n;
		while(L<R)
		{
			ll Mid=(L+R+1)/2;
			if(ask(Mid,n)==0)
				R=Mid-1;
			else
				L=Mid;
		}
		_3=L;
		_2=all^_1^_3;
		print(_1,_2,_3);
	}
}
int main()
{
    _t_=1;
    cin>>_t_;
    while(_t_--)
        solve();
    QwQ;
}
posted @ 2024-11-04 00:02  wangmarui  阅读(8)  评论(0编辑  收藏  举报