[CF1375F] Integer Game
\(\text{Problem}:\)题目链接
\(\text{Solution}:\)
记一个状态为有序三元组 \((x,y,z)\)。
当 \(x<y<z\) 时,考虑先手一步必胜的情况:当 \(z-y=y-x\) 且后手上一步选了 \(z\) 时,先手给定 \(z-y\) 这个数。
当 \(x<y<z\) 时,如果先手给定 \(2z-y-x\),则后手只有选择加给 \(z\) 才能避免出现先手一步必胜的情况。所以先手两步必胜的情况是:后手上一步选了 \(z\),先手给定 \(2z-y-x\)。
这说明只要后手选择了 \(max\{x,y,z\}\),先手就可以在两步内必胜。所以先手的目标是,给定一个数 \(k\),使得后手选择 \(x,y,z\) 其中一个加上 \(k\),成为最大值。
观察 \(k\) 的范围远大于初始的 \(x,y,z\),所以初始把 \(k\) 设为 \(INF(10^9\leq INF \leq 10^{12})\) 即可。先手三步内必胜。
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
using namespace std;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int a[5],INF=1e11;
struct Node { int w,id; }b[5];
inline bool cp(Node x,Node y) { return x.w<y.w; }
signed main()
{
a[1]=read(), a[2]=read(), a[3]=read();
printf("First\n");
printf("%lld\n",INF), fflush(stdout);
int x;
scanf("%lld",&x);
a[x]+=INF;
for(ri int i=1;i<=3;i++) b[i]=(Node){a[i],i};
sort(b+1,b+4,cp);
if(b[3].w-b[2].w==b[2].w-b[1].w)
{
printf("%lld\n",b[3].w-b[2].w), fflush(stdout);
scanf("%lld",&x);
return 0;
}
int g=b[3].w*2-b[2].w-b[1].w;
printf("%lld\n",g), fflush(stdout);
scanf("%lld",&x);
a[x]+=g;
for(ri int i=1;i<=3;i++) b[i]=(Node){a[i],i};
sort(b+1,b+4,cp);
printf("%lld\n",b[3].w-b[2].w), fflush(stdout);
scanf("%lld",&x);
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。