【CF1033G】Chip
【CF1033G】Chip
by AmanoKumiko
Description
\(Alice\)和\(Bob\)玩游戏
有\(n\)堆石子,第\(i\)堆有\(v_i\)个
\(Alice\)和\(Bob\)可以各自选择一个\([1,m]\)中的整数
令其分别为\(a,b\)
然后\(Alice\)只能恰好取\(a\)个,\(Bob\)只能恰好取\(b\)个
对于所有情况下的\((a,b)\)对
求:
\(1.Alice\)必胜的情况
\(2.Bob\)必胜的情况
\(3.\)先手必胜
\(4.\)后手必胜
Input
第一行两个整数\(n,m\)
第二行\(n\)个整数读入\(a\)
Output
一行四个整数表示答案
Sample Input
2 20
4 5
Sample Output
82 82 6 230
Data Constraint
\(1\le n\le 100,1\le m\le 10^5\)
Solution
首先可以发现,\(v_i\)对\((a+b)\)取模之后对局面无影响
假定\(a<b\),那么
\(1.v_i<a\),这个点无用
\(2.a\le v_i<b\),这个点成了\(A\)的专属点
\(3.b\le v_i<2a\),那么这个点只会被其中一个人恰好取一次
\(4.v_i\ge 2a\),那么\(A\)若取了它,就变成了\(2.\)
可以发现\(A\)只要有一个专属点就必胜
\(O(n^2m)\)就是枚举\(a,b\),然后分情况讨论
考虑优化
由于第一二种答案一定是相等的
所以只对后面两种计数
可以改成枚举\(a+b\),然后考虑钦定先手/后手必败
可以发现\(a,b\)一定在同一个区间,即\((v_i,v_{i+1}]\)
那么稍微分讨一下即可
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
#define N 110
int n,m,tmp[N];
LL fir,sec,v[N];
int mod(LL x,int y){return x-x/y*y;}
int main(){
scanf("%d%d",&n,&m);
F(i,1,n)scanf("%lld",&v[i]);
F(s,2,m*2){
F(i,1,n)tmp[i]=mod(v[i],s);
sort(tmp+1,tmp+n+1);
tmp[n+1]=s-1;
F(i,1,n+1){
int L=tmp[i-1]+1,R=min(m,tmp[i]);
if(!((n-i+1)&1)){
L=max(L,(tmp[n]>>1)+1);
R=min(R,s-L);
L=max(L,s-R);
sec+=max(0,R-L+1);
}else{
L=max(L,(tmp[n-1]>>1)+1);
R=min(R,s-L);
L=max(L,s-R);
fir+=max(0,R-L+1);
}
}
}
LL sum=1ll*m*m-fir-sec>>1;
printf("%lld %lld %lld %lld",sum,sum,fir,sec);
return 0;
}