题意
一个01串,给定0的个数n,1的个数m,询问多少个不同01串通过不断进行一种操作后得到一个字符g(0或1)
操作如下:
将01串最后两个数字取出,如果两个都是0,则在01串末尾放回1,否则放回0,直到01串只剩1个字符
给出n,m,g
题解
首先n或m为0的情况单独处理。
下面思考如下规律(===
代表任意非空01串)
1=== ans:0 1 ans:1
01=== ans:1 01 ans:0
001=== ans:0 001 ans:1
0001=== ans:1 0001 ans:0
00001=== ans:0 00001 ans:1
......
按照这个规律求求组合数来计算答案。
代码
/// by ztx
/// blog.csdn.net/hzoi_ztx
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v) for(i=v.begin();i!=v.end();i++)
#define r(x) read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
#define maxn 200010LL
#define mod 1000000007LL
int inv(ll x) {
ll ret = 1;
int p = mod-2;
for (; p; p >>= 1, x *= x, x %= mod) if (p & 1) ret *= x, ret %= mod;
return ret;
}
ll fact[maxn];
int C(int n,int m) {
if (m > n) return 0;
if (m <= 0 || m == n) return 1;
return fact[n]*inv(fact[m]*fact[n-m]%mod)%mod;
}
int main() {
int n, m, g, i, ans;
r(n), r(m), r(g);
fact[0] = 1;
Rep (i,1,n+m) fact[i] = fact[i-1]*i%mod;
if (n == 0) {
if (m == 1) puts(g?"1":"0");
else puts(g?"0":"1");
goto END;
}
if (m == 0) {
if (n%2==0 && g) puts("1");
else if (n%2==1 && !g) puts("1");
else puts("0");
goto END;
}
ans = 0;
if (g) {
for (i = 2; i < n+m; i += 2) {
ans += C(n+m-i,m-1);
ans %= mod;
}
if (m==1 && (n+m)%2) ans ++ , ans %= mod;
} else {
for (i = 1; i < n+m; i += 2) {
ans += C(n+m-i,m-1);
ans %= mod;
}
if (m==1 && (n+m)%2==0) ans ++ , ans %= mod;
}
printf("%d\n", ans);
END: getchar(), getchar();
return 0;
}