Loading

【题解】CF1536F Omkar and Akmar

结论:无论怎么走后手一定赢。

这应该是这道题中最难想到的。

这里的一定赢是指不用考虑任何策略,都能躺赢(

反证法,假定先手赢了,此时场上有奇数个位置被填了,那么一定存在去掉空格后相邻的两个格子颜色相同,它们之间还能再填至少一个,所以后手必胜。

然后就非常简单了,我们计算最终状态,如果最终状态有 \(k\) 个位置被填了,那么有 \(k!\) 种方案达到这个状态。

\(k\) 一定是偶数,我们枚举 \(k\) ,计算有多少种最终状态。

最终状态去掉空格后一定是形如 \(AB\cdots AB\) 或者 \(BA\cdots BA\) 的长度为 \(k\) 的串,一个 \(AB\) 中最多只能插入一个空格。

由于是环,讨论一下第一个位置是否为空格。

如果第一个位置不是空格,方案数为 \(2\binom{k}{n-k}\)

如果第一个位置为空格,方案数为 \(2\binom{k-1}{n-k-1}\)

这样我们就得到了答案。

\[Ans=2\sum\limits_{1\le i\le \left\lfloor\frac{n}{2}\right\rfloor}(2i)!\binom{2i}{n-2i}+(2i)!\binom{2i-1}{n-2i-1} \]

时间复杂度 \(\mathcal{O}(n+\log P)\)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 1000005
#define P 1000000007
using namespace std;
int n,fac[N],inv[N];
int Pow(int x,int y){
	int now=1;
	for(;y;y>>=1,x=1LL*x*x%P)if(y&1)now=1LL*now*x%P;
	return now;
}
int C(int x,int y){
	if(x<0||y<0||x<y)return 0;
	return 1LL*fac[x]*inv[y]%P*inv[x-y]%P;
}
// Sharpness V
int main(){
	scanf("%d",&n);fac[0]=1;
	rep(i,1,n)fac[i]=1LL*i*fac[i-1]%P;
	inv[n]=Pow(fac[n],P-2);
	pre(i,n-1,0)inv[i]=1LL*inv[i+1]*(i+1)%P;
	int ans=0;
	rep(i,1,n/2){
		int cur=i*2;
		ans=(ans+2LL*fac[cur]*(C(cur,n-cur)+C(cur-1,n-cur-1)))%P;
	}
	printf("%d\n",ans);
	return 0;
} 
posted @ 2021-06-07 12:50  7KByte  阅读(72)  评论(0编辑  收藏  举报