Codeforces 336D. Vasily the Bear and Beautiful Strings 解题报告

题目

题意:

一个01串,0刚好有n个,1刚好有m个,每次将最后的两个数字变成一个,如果是00则变成1,否则变成0.已知n,m和最后剩的一个数字,求原串可能有多少种。

题解:

由题,倒过来做,1->00,而0->01,10,11,进一步地0->100,000,10,100,也即是说最后的0可以在前面塞任意多个00或10或1,最后还是0.

假如原串最后是0的话,枚举中间00、10和1的个数就可以用组合数算出来,又因为0的数量只跟00和10的数量有关,所以只要枚举00的数量那10和1的数量都知道了。

如果原串最后是1,相当于把这个1再拆开,那么变成上面的做法,只不过n+2,m-1,且中间塞的最后一个数必须是0.


//Time:312ms
//Memory:4704KB
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <set>
#define MAXN 300010
#define INF 1000000007
#define MOD 1000000007
#define MP(x,y) make_pair(x,y)
#define FI first
#define SE second
#define EPS 1e-8
using namespace std;
long long p[MAXN],np[MAXN];
int pow_mod(long long a,int p)
{
    long long ret=1;
    while(p)
    {
        if(p&1) ret=ret*a%MOD;
        p>>=1,a=a*a%MOD;
    }
    return ret;
}
int cal(int n,int m,bool ty)
{
    int ret=0;
    if(n<0||m<0)    return 0;
    if(ty&&n==0&&m!=0)    return 0;
    if(n==0&&m==0)  return 1;
    for(int i=0;2*i<=n;++i)
    {
        int j=n-2*i,k=m-j;
        if(j<0||k<0)    continue;
        ret=(ret+p[i+j]*np[i]%MOD*np[j]%MOD*p[i+j+k-ty]%MOD*np[k]%MOD*np[i+j-ty]%MOD)%MOD;
    }
    return ret;
}
int main()
{
    //freopen("/home/moor/Code/input","r",stdin);
    int n,m,g,ans;
    p[0]=1;
    np[0]=1;
    for(int i=1;i<MAXN;++i) p[i]=p[i-1]*i%MOD,np[i]=pow_mod(p[i],MOD-2);
    while(scanf("%d%d%d",&n,&m,&g)==3)
    {
        --n;
        if(g==1)    --n;
        ans=cal(n,m,0)+cal(n+2,m-1,1);
        printf("%d\n",ans%MOD);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值