题目大意
有nnn堆石子,第iii堆有xix_ixi个。AliceAliceAlice和BobBobBob轮流取石子,先后手未定,AliceAliceAlice每次从一堆中取走aaa个,BobBobBob每次从一堆中取走bbb个,不能操作者输。
不难发现只有四种情况:AliceAliceAlice必胜,BobBobBob必胜,先手必胜,后手必胜。你需要选若干堆石子(总共有2n2^n2n种选法),AliceAliceAlice和BobBobBob只能在你选出的堆中取,问以上四种情况对应的方案数。
1≤n≤1051\leq n\leq 10^51≤n≤105,1≤a,b,xi≤1091\leq a,b,x_i\leq 10^91≤a,b,xi≤109
题解
不妨设a<ba<ba<b
首先,我们可以将每一堆的石子数量模(a+b)(a+b)(a+b)。为什么可以这样呢?
如果模(a+b)(a+b)(a+b)后可以证明一方必胜
- 如果这一方是后手,则只要先手拿的那一堆大于等于(a+b)(a+b)(a+b),则取那一堆;否则按最优策略取对应的那一堆
- 如果这一方是先手,则先按最优策略取一堆,然后它就是后手了,接着按后手的方法来取就行了
然后我们可以分类讨论,不妨设a<ba<ba<b。
- 如果xi<ax_i<axi<a,则这一类没有用
- 如果a≤xi<ba\leq x_i<ba≤xi<b,则存在则aaa必胜
- 如果b≤xi<2ab\leq x_i<2ab≤xi<2a,答案只与这一类的奇偶性相关
- 如果xi≥2ax_i\geq 2axi≥2a,在没有第二类石子的条件下
- 存在至少两个则aaa必胜
- 存在一个且第三类石子个数为偶数则先手必胜
- 存在一个且第三类石子个数为奇数则aaa必胜
- 不存在且第三类石子个数为奇数则先手必胜
- 不存在且第三类石子个数为偶数则后手必胜
时间复杂度为O(n)O(n)O(n)。
code
#include<bits/stdc++.h>
using namespace std;
const int N=100000;
int n,a,b,fl=0,x[100005];
int v1=0,v2=0,v3=0,v4=0;
long long ans1=0,ans2=0,ans3=0,ans4=0,jc[N+5],ny[N+5];
long long mod=1000000007;
long long mi(long long t,long long v){
if(!v) return 1;
long long re=mi(t,v/2);
re=re*re%mod;
if(v&1) re=re*t%mod;
return re;
}
void init(){
jc[0]=1;
for(int i=1;i<=N;i++) jc[i]=jc[i-1]*i%mod;
ny[N]=mi(jc[N],mod-2);
for(int i=N-1;i>=0;i--) ny[i]=ny[i+1]*(i+1)%mod;
}
long long C(int x,int y){
return jc[x]*ny[y]%mod*ny[x-y]%mod;
}
int main()
{
init();
scanf("%d%d%d",&n,&a,&b);
if(a>b){
fl=1;swap(a,b);
}
for(int i=1;i<=n;i++){
scanf("%d",&x[i]);
x[i]=x[i]%(a+b);
if(x[i]<a) ++v1;
else if(x[i]>=a&&x[i]<b) ++v2;
else if(x[i]>=b&&x[i]<2*a) ++v3;
else ++v4;
}
long long tmp=mi(2,v1+v3+v4);
for(int i=1;i<=v2;i++){
ans1=(ans1+C(v2,i)*tmp%mod)%mod;
}
tmp=mi(2,v1);
for(int i=0;i<=v3;i++){
if(i&1) ans3=(ans3+C(v3,i)*tmp%mod)%mod;
else ans4=(ans4+C(v3,i)*tmp%mod)%mod;
}
tmp=mi(2,v1)*v4%mod;
for(int i=0;i<=v3;i++){
if(i&1) ans1=(ans1+C(v3,i)*tmp%mod)%mod;
else ans3=(ans3+C(v3,i)*tmp%mod)%mod;
}
tmp=mi(2,v1+v3);
for(int i=2;i<=v4;i++){
ans1=(ans1+C(v4,i)*tmp%mod)%mod;
}
if(fl) swap(ans1,ans2);
printf("%lld %lld %lld %lld",ans1,ans2,ans3,ans4);
return 0;
}
文章描述了一个关于石子的游戏,Alice和Bob轮流从n堆石子中取走一定数量。通过模运算简化问题,分析了四种获胜情况:Alice必胜、Bob必胜、先手必胜、后手必胜。对于每种情况,文章给出了具体的策略和计数方法,如考虑石子数量对(a+b)的余数,以及不同数量范围内的石子对胜负的影响。
521

被折叠的 条评论
为什么被折叠?



