「雜題亂刷2」CF2036G

wangmarui發表於2024-11-04

這題 *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;
}