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

来源:互联网 发布:mac应用快捷键设置 编辑:程序博客网 时间:2024/05/29 08:20

题目

题意:

一个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-8using 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;}


原创粉丝点击