题意:
一个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;
}