CodeForces -336D. Vasily the Bear and Beautiful Strings(组合数学)

题目链接

题意:
就是现在如果给出一个串S是一个由01包含的串将这个串进行题意所说的变化, 每次取最后两个字符, 如果是"00"就变成“1”加到末尾, 如果是"01"或“10”或“11”, 就变成“0”来代替其加到末尾, 反复执行直到该串只剩下一个字符为止

现在给出n, m, g (0 <= n, m <= 10^5, n + m >= 1, g == 0 || g == 1)

求出如果一个串原本有n个0, m个1, 进行上诉变化之后得到的字符是g, 问原来的串的可能性有多少种, 最终结果多10^9 + 7取模输出
题解:
首先我们看到这个题肯定能得到这样的结论
(g=0的方案数)+(g=1的方案数)=C(n+m,m);
所以不论他让我们求(g=0的方案数)还是(g=1的方案数)我们都可以转换成求(g=0的方案数).为什么要转换成(g=0)呢?往下看。
分析题意:我们知道除了 00 00 00生成 1 1 1,其他的都生成 0 0 0。所以我们知道, 1 1 1不论跟什么放一起一定是 0 0 0那么,所以只要是1开头的串一定是0.那么我们就可以在确定偶数个0连续的基础上把1开头的串放在他们后面那一定是0,因为想到与奇数个0.
其实就是这种形式

00001...... 这是确定了4个0和1个1,所以(n+m-4-1)这个么多数组合就行了也就是C(n+m-4-1,m-1);

我们还需要特判一种情况 就是m=1就是只有一个1.

  1. 如果n是奇数,那么我们漏了一种把1放在最前面的情况,后面是奇数个0.
  2. 如果n是偶数,那么我们多加了一种,n个0+100001这种情况,这种结果是1.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+7;
const int mod=1e9+7;
ll n,m,cnt;
ll fac[maxn],infac[maxn];
ll qpow(ll a,ll b) {
    
    
    ll sum=1;
    while(b) {
    
    
        if(b&1) sum=sum*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return sum;
}
void init() {
    
    
    fac[0]=fac[1]=1;
    for(int i=2; i<=200000; i++) {
    
    
        fac[i]=fac[i-1]*i%mod;
    }
    for(int i=200000; i>=0; i--) {
    
    
        infac[i]=qpow(fac[i],mod-2);
    }
}
ll C(ll n,ll m) {
    
    
    return fac[n]*infac[m]%mod*infac[n-m]%mod;
}


int main() {
    
    
    ll g;
    cin>>n>>m>>g;
    if(n==0) {
    
     ///没有0 除了一个1之外不能构成1
        if(g==0) {
    
    
            if(m==1) printf("0\n");
            else puts("1");
        } else {
    
    
            if(m==1) puts("1");
            else puts("0");
        }
        return 0;
    }
    if(m==0) {
    
     ///没有1 
        if(g==1) {
    
     ///奇数个0可以构成1
            if(n&1)printf("0\n");
            else puts("1");
        } else {
    
    
            if(n&1)puts("1");
            else puts("0");
        }
        return 0;
    }
    init();
    ll all=C(n+m,m);
    ll ans=0;///0的方案数
    for(int i=0; i<=n; i+=2) {
    
    
        ans=(ans+C(n-1-i+m,m-1))%mod;///除去确定的偶数个0和一个1
    }
    if(m==1&&(n&1)==0) {
    
    
        ans=(ans-1+mod)%mod;
    }
    if(m==1&&(n&1)) {
    
    
        ans=(ans+1)%mod;
    }
    if(g==0) printf("%lld\n",ans);
    else printf("%lld\n",(all-ans+mod)%mod);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45911397/article/details/110730688