【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;
}
posted @ 2022-03-31 19:46  冰雾  阅读(20)  评论(0编辑  收藏  举报