专栏文章

题解:CF1536F Omkar and Akmar

CF1536F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minyt62c
此快照首次捕获于
2025/12/02 10:34
3 个月前
此快照最后确认于
2025/12/02 10:34
3 个月前
查看原文
对于这些博弈论但是数据范围很大的题目一定要找一些特殊性质。
考虑最终的局面是什么样的。如果出现空格,这个空格两边一定是两个不同的字母,要不然就是两个不同的字母在相邻的位置上。
因此整个环去掉空格后一定是 ABABABABAB 交错或者 BABABABABA 交错。从这个就可以看出 A 的个数一定等于 B 的个数,因此无论后手如何操作一定会赢,因此无论如何操作都是一个人的最优策略。
所以就对最终状态计数即可。
考虑枚举去掉空格后有多少个字母 ii,这里必须保证 ii 是偶数,(因为总共操作了偶数次),这样相当于插在 ii 个位置中选择 nin-i 个位置填空格。由于还需要操作 ii 次,所以还需要乘以 ii 的圆排列数(这个时候我们可以先不确定序列开头的下标为 11)。
然后从每一个下标开始都可以有这个序列,同时 AB 的地位等价,所以还需要乘以 2n2n
总的答案就是如下的式子:
2ni=2,2in(ini)×(i1)!2n\sum_{i=2,2|i}^n \binom{i}{n-i}\times(i-1)!
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
constexpr ll maxn=1e6+5,modd=1e9+7;
ll fac[maxn],inv[maxn],n,ans;
ll qpow(ll a,ll b){
    ll ret=1;
    while(b){
        if(b&1)ret=(ret*a)%modd;
        a=(a*a)%modd;
        b>>=1;
    }
    return ret;
}
void init(){
    fac[0]=1;
    for(ll i=1;i<maxn;i++){
        fac[i]=(fac[i-1]*i)%modd;
    }
    inv[maxn-1]=qpow(fac[maxn-1],modd-2);
    for(ll i=maxn-2;i>=0;i--){
        inv[i]=(inv[i+1]*(i+1))%modd;
    }
}
ll C(ll n,ll m){
    if(n<m)return 0;
    if(m==0)return 1;
    return fac[n]*inv[m]%modd*inv[n-m]%modd;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    init();
    cin>>n;
    for(ll i=1;i<=n;i++){
        if(i&1)continue;
        ans=(ans+C(i,n-i)*fac[i-1]%modd)%modd;
    }
    cout<<(ans*2*n%modd+modd)%modd<<"\n";
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...