[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;
}
posted @ 2021-02-23 16:53  zkdxl  阅读(49)  评论(0编辑  收藏  举报