1. 程式人生 > 其它 >CF1375F Integer Game 題解

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;
}