CF1375F Integer Game 题解

Codeforces
Luogu

Description.

给你 \(a,b,c\),先手选择一个 \(x\in[1,10^12]\),后手选择 \(a,b,c\) 中一个数。
然后在后手选择的数上加 \(k\),你需要吊打 spj。

Solution.

差一步啊啊啊啊啊啊啊啊啊啊,就真差一步就想打了啊啊啊啊啊。

点击查看我差一步的所有笔记
首先有 abc 每次 +=k  
什么样的情况下先手会赢  
后手不能连续对同一堆石子进行操作  
那先手首先随便钦定一个,然后 +=k  
后手选一个  
先手选剩下两个的差  
后手加到剩下两个偏大的里面去  
所以相当于先手胜利的条件是局面构成等差数列且上一轮对最大的进行操作  
但是后手肯定不会让这种局面出现,所以一个局面是先手必胜的当且仅当
那也就相当于 max > mid*2 - min  
否则我们需要证明后手必胜  

首先,手模样例发现,如果 2*mid > min + max,此时先手必胜  
同时有 2*c-a-b 加上后肯定可以变成上面的式子  
他选择 2*mid - min - max 然后后手只能加中间然后继续选择 2*mid' - min - max 后手就 lose 了  
如果 2*mid <= min + max 那后手先加到 max 上,所以先手先出 1
相当于现在有 a b c 且满足 b-a < c-b
划分成四个区间,[0,b-a]、[b-a,c-b]、[c-b,c-a]、[c-a,+inf]
先手尝试让 min' + max' - 2*(sum'-min'-max') 尽可能小
min' + max' - 2*(sum + x - min' - max')
3*min' + 3*max' -2*sum - 2*x 小
后手会尝试让他变大,所以会加到 max 上去
如果不能加 max 那他会加到 min 上去
3*min(mid,min+x)+3*max'-2*sum-2*x
如果 x 很大,足以改变 max,显然不优
如果 x 很小,肯定递增
如果 x 中等,答案不变
所以 x=mid-min,式子是 3*mid+3*max-2*sum-2*x
所以先手给的肯定是 mid - min,后手肯定会把它加到最小值上去

已经胡出了 \(2\times \text{mid} > \min + \max\),然后 \(2\times \max -\min -\text{mid}\) 这一步没想到,看了题解知道后最后一步也是自己想出来的。

Coding.

点击查看代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
pair<ll,int>a[5];
inline void out(ll v)
{
	printf("%lld\n",v),fflush(stdout);ll x;read(x);
	for(int i=1;i<=3;i++) if(a[i].second==x) a[i].first+=v;
	sort(a+1,a+4);if(x==0) exit(0);
}
int main()
{
	for(int i=1;i<=3;i++) read(a[i].first),a[i].second=i;
	puts("First"),fflush(stdout);
	out(1000000005);
	out(a[3].first*2-a[2].first-a[1].first);
	out(a[3].first-a[2].first);
	return 0;
}
原文地址:https://www.cnblogs.com/pealfrog/p/15414133.html