KUPC 2014 D - ハミング

問題

0, 1のみからなる長さの同じ二つの文字列s, tが与えられる。
s, tに長さが等しく、sからのハミング距離がd1で、tからのハミング距離がd2であるような文字列はいくつあるか。
mod 10^9 + 7で求めよ。

制約条件

s ≦10^5

方針

同じ位置にある文字によって場合わけ。
s[i] == t[i]の場合、d1, d2を共に増やすか、共に増やさないか選べる。
s[i] != t[i]の場合、d1, d2のどちらか片方を増やして、もう片方をそのままにするか選べる。


s[i] == t[i]の個数をa個として、このうちx個でd1を増やす、
s[i] != t[i]の個数をb個として、このうちy個でd1を増やすとすると、

d1 = x + y
d2 = x + b - y
となる。xを決めるとyは一意に定まるので、xを全通り試せばよい。
yの範囲がマイナスになったりしたらそのxはダメ。


で、xが決まったら具体的にどこを選ぶのかがaCx通り, yの選び方がbCy通りなのでそれを掛ければよい。

ソースコード

const int mod = inf + 7;
string s, t;
int d, e;

inline ll inv(ll a)
{
	ll b = mod, x = 1, y = 0;
	while(b){
		ll t = a / b;
		a -= t * b;
		swap(a, b);
		x -= t * y;
		swap(x, y);
	}
	return (mod + x % mod) % mod;
}
ll f[100010];
ll C(int n, int k){
	return f[n] * inv(f[k]) % mod * inv(f[n - k]) % mod;
}

int main(){
	f[0] = 1;
	rep(i, 100010) f[i + 1] = f[i] * (i + 1) % mod;
	
	
	cin >> s >> d >> t >> e;
	ll ans = 0;
	
	int n = s.size();
	int a = 0, b = 0;
	
	rep(i, n){
		if(s[i] == t[i]) a++;
		else b++;
	}
	
	for(int i = 0; i <= a; i++){
		int j = d - i;
		if(e != i + b - j) continue;
		if(j < 0 || b - j < 0) continue;
		
		ans += C(a, i) * C(b, j) % mod;
		ans %= mod;
	}
	cout << ans << endl;
	
	return 0;
}