「杂题乱刷」CF1934D2
感觉 D2 比 D1 简单 /kx /kx /kx
算法一
发现一个数 \(x\) 为 \(2^k(0 \le k)\) 时一定无法拆分。
此时直接分讨即可。
算法二
发现一个数 \(x\) 满足化为二进制下数位和为 \(2\),可以拆成两个 \(2\) 的非负整数次幂的数。
此时直接分讨即可。
算法三
为方便读者理解,下文中使用 \(f(x)\) 表示 \(x\) 在二进制下的数位和。
分讨一个可拆分的数 \(x\):
-
若 \(x \bmod 2 = 0\),则有 \(f(p1) \bmod 2 \neq f(p2) \bmod 2\),此时后手可选择先手拆分后的数位和为偶数的二进制数,先手必败。
-
若 \(x \bmod 2 = 1\),则有 \(f(p1) \bmod 2 = f(p2) \bmod 2\),此时先手可将此数拆分成两个数位和为奇数的二进制数,先手必胜。
直接从最高位开始操作,发现每次操作这个二进制数的位数都会减少 \(1\),因此操作次数最多为 \(\log_2(n)\) 次,可以通过此题。
参考代码:
总结
此题是一道简单的构造题。
点击查看代码
/*
Tips:
你数组开小了吗?
你MLE了吗?
你觉得是贪心,是不是该想想dp?
一个小时没调出来,是不是该考虑换题?
*/
#include<bits/stdc++.h>
using namespace std;
#define map unordered_map
#define forl(i,a,b) for(register long long i=a;i<=b;i++)
#define forr(i,a,b) for(register long long i=a;i>=b;i--)
#define forll(i,a,b,c) for(register long long i=a;i<=b;i+=c)
#define forrr(i,a,b,c) for(register long long i=a;i>=b;i-=c)
#define lc(x) x<<1
#define rc(x) x<<1|1
#define mid ((l+r)>>1)
#define cin(x) scanf("%lld",&x)
#define cout(x) printf("%lld",x)
#define lowbit(x) x&-x
#define pb push_back
#define pf push_front
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
//#define endl '\n'
#define QwQ return 0;
#define ll long long
#define lcm(x,y) x/__gcd(x,y)*y
#define Sum(x,y) 1ll*(x+y)*(y-x+1)/2
ll t;
ll n,p1,p2;
/*ll f(ll x,ll opt)
{
if(opt==0)
{
ll sum=0;
while(x)
x/=2,sum++;
return 1ll<<(63-__builtin_clzll(x));
return 1ll<<sum;
}
else if(opt==1)
{
ll sum=0,lastx=x;
while(x)
sum+=x%2,x/=2;
sum=__builtin_popcountll(x);
if(pd==1)
{
if(sum%2)
cout<<"second"<<endl;
else
cout<<"first"<<endl;
}
if(sum%2==0 && pd)
cout<<f(lastx,0)<<' '<<(f(lastx,0)^lastx)<<endl;
pd=0;
return __builtin_popcountll(x)&1;
return sum%2;
}
else
{
ll p1,p2;
cin>>p1>>p2;
if(p1<=0 && p2<=0)
return 0;
if(f(p1,1))
cout<<f(p2,0)<<' '<<(p2^f(p2,0))<<endl;
else
cout<<f(p1,0)<<' '<<(p1^f(p1,0))<<endl;
return 1;
}
}*/
ll f(ll opt,ll x){
if(!opt)
return __builtin_popcountll(x)%2;
else
return 1ll<<(63-__builtin_clzll(x));
}
void solve()
{
/* pd=1;
cin>>n;
f(n,1);
forl(i,1,1e18)
if(!f(0,2))
break;*/
cin>>n;
cout<<(f(0,n)?"second":"first")<<endl;
if(!f(0,n))
cout<<f(1,n)<<' '<<(n^f(1,n))<<endl;
forl(i,1,1e18)
{
cin>>p1>>p2;
if(p1<=0 && p2<=0)
return ;
if(f(0,p1))
cout<<f(1,p2)<<' '<<(p2^f(1,p2))<<endl;
else
cout<<f(1,p1)<<' '<<(p1^f(1,p1))<<endl;
}
}
int main()
{
// IOS;
t=1;
cin>>t;
while(t--)
solve();
/******************/
/*while(L<q[i].l) */
/* del(a[L++]);*/
/*while(L>q[i].l) */
/* add(a[--L]);*/
/*while(R<q[i].r) */
/* add(a[++R]);*/
/*while(R>q[i].r) */
/* del(a[R--]);*/
/******************/
QwQ;
}