1. 程式人生 > 其它 >CF1033G Chip Game 題解

CF1033G Chip Game 題解

Luogu
Codeforces

Description.

\(n\) 堆石子,Alice Bob 打隔膜,他們分別從 \([1,m]\) 中選一個值,設為 \(A\)\(B\)
Alice Bob 分別可以從任意一堆中取出 \(A\)\(B\) 個石子,不能操作的人輸。
問對於不同的 \(A,B\),以下四種狀態的方案數分別是多少。

  1. Alice 贏
  2. Bob 贏
  3. 先手贏
  4. 後手贏

\(n\le 100,m\le 10^5\)

Solution.

首先,發現 Alice 贏和 Bob 贏本質相同,方案數相同。
所以我們只需要算出先手贏、後手贏的方案數容斥就行了。

同時,顯然的性質就是狀態 \(\{v_i\}\)

和狀態 \(\{v_i+k_i(a+b)\}\) 等價。
證明顯然,贏的人肯定可以按照原來狀態,如果後手選了就跟他把 \(k_i\) 減一。

那我們可以考慮列舉 \(a+b\),剩下了所有的 \(v_i\le (a+b)\)
考慮先手贏,可能會有這幾種情況

  1. \(\exists i\in[1,n],a\le v_i< b\),是因為先手可以苟著 \(v_i\) 最後取。
  2. \(\exists i\in[1,n],2a\le v_i\),有 \(2a\le v_i\le a+b\),先手可以先取一個 \(a\) 再苟。

先手能苟的情況也就只有這兩種。
考慮不能苟,那也就是說 \(\sum[v_i\ge b]\)

是偶數。
所以先手必敗的情況是沒有情況 1 和 2 且是偶數。
同理,後手贏的情況有以下幾種

  1. \(\exists i\in[1,n],b\le v_i< a\)
  2. \(\sum[2b\le v_i]\ge 2\)

考慮 \(\forall i\in[1,n],a\le v_i<b\) 不成立,則肯定有 \(a,b\) 在同一個 \((v_i,v_{i+1}]\) 值域區間內。
所以我們可以列舉這個值域區間,複雜度 \(O(n)\),可以 \(O(1)\) 算出 \(\sum[v_i\ge b]\)
考慮 \(2a\le v_i\) 也不成立,所以肯定有 \(a>\frac {v_i}2\)

,直接找到最大的 \(v_i\) 就行了。
後手的話考慮次大就行了。

Coding.

點選檢視程式碼
//Coded by leapfrog {{{
//Coded on 2021.10.26
//是啊,你就是那隻鬼了,所以被你碰到以後,就輪到我變成鬼了
#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...);}//}}}
int n,m,b[105];ll a[105],rfs,rsc;
int main()
{
	read(n,m);for(int i=1;i<=n;i++) read(a[i]);
	for(int S=2;S<=m+m;S++)
	{
		for(int i=1;i<=n;i++) b[i]=a[i]%S;
		b[n+1]=0,b[n+2]=S-1,sort(b+1,b+n+3);
		for(int i=n+2;i>1;i--)
		{
			int fg=(n+2-i)&1,l=max(b[i-1],b[n+!fg]/2)+1,r=min(b[i],m);
			(fg?rfs:rsc)+=max(min(r,S-l)-max(l,S-r)+1,0);
		}
	}
	ll rs=(1ll*m*m-rfs-rsc)>>1;
	return printf("%lld %lld %lld %lld\n",rs,rs,rfs,rsc),0;
}