CF 1045 H.自己探求
アカウントに文字列の構造を取ることでなければなりません
1...0....1....0.....1...
しながら、このようにして、(\ 01 \)と\(10 \)が表示される交互点を回します
最初の文字列の長さがなければならない\(A + B + C + D + 1 \) (代表\(00,01,10,11 \)数)、及び第一されなければならない\(1 \)も満たしている必要があり\ (B = C \ B = C-LOR。1 \) 、波の数は限定とは見なされません
私たちは、実際には、我々はすべて配置する必要があり、ことがわかった\(0 \) 、その後、ターニングポイントとして番号を選択し、(1 \)\それに直接回すに従って残りを埋めるために、やって
注目\(0 \)と(1 \)\数である\を(A + C \)と\(B + D + 1 \ )
次いで、最初の場所の転換点は、一度だけ発生する必要があり、そのためプログラムの数である\(\ binom {A + C -1}、{C} \) 及び(\ Binom {B + D} {B} \)\、乗算原理その上
その後、我々は最高のビットスタッフィングから開始し、限界を考えます
現在のビットがある場合は、\(0 \) 、あなただけ埋めることができます\(0 \)をバック埋めるために継続します
ある電流がある場合は、\(1 \) 、埋める\(0 \)バックが簡単に埋めることができた後、あなたはほとんど制限がないことで数えることができますが、最高レベルの帝国がさ(0 \)\を、埋める\(1 \)を上また、埋めるために今後も継続
なお、小さなノート境界裁判官を充填する工程、の配列の境界は、どのようなそうでないかもしれません
コード:
#include <cstdio>
#include <cctype>
#include <cstring>
#include <vector>
#include <algorithm>
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
int f=0;x=0;char c=gc();
while(!isdigit(c)) f|=c=='-',c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
if(f) x=-x;
}
const int N=2e5+1;
const int mod=1e9+7;
char s[N],t[N];
int fac[N],inv[N];
inline void add(int &x,int y){x+=y;if(x>=mod) x-=mod;}
#define mul(a,b) (1ll*(a)*(b)%mod)
inline int qp(int d,int k)
{
int f=1;
while(k)
{
if(k&1) f=mul(f,d);
d=mul(d,d);
k>>=1;
}
return f;
}
int C(int m,int n)
{
if(m==n) return 1;
return mul(fac[m],mul(inv[m-n],inv[n]));
}
int cal(int c00,int c01,int c10,int c11,char *s)
{
int n=strlen(s+1),l=c00+c01+c10+c11;
if(c10!=c01&&c10!=c01+1) return 0;
if(n>l+1) return mul(C(c00+c10-1,c10-1),C(c11+c01,c01));
if(n<l+1) return 0;
int pre=1,ret=0;
for(int i=2;i<=n;i++)
{
if(s[i]=='0')
{
if(pre) --c10;
else --c00;
pre=0;
}
else
{
if(pre) --c10;
else --c00;
if(c01!=c10||c01!=c10+1) add(ret,mul(C(c00+c10,c10),C(c11+c01-1,c01-1)));
if(pre) ++c10;
else ++c00;
if(pre) --c11;
else --c01;
pre=1;
}
if(c00<0||c01<0||c10<0||c11<0) break;
}
return ret;
}
int ck(int c00,int c01,int c10,int c11,char *s)
{
int n=strlen(s+1),l=c00+c01+c10+c11;
if(n!=l+1) return 0;
int pre=s[1]-'0';
for(int i=2;i<=n;i++)
{
if(pre)
{
if(s[i]=='1') --c11;
else --c10;
}
else
{
if(s[i]=='1') --c01;
else --c00;
}
pre=s[i]-'0';
}
return !c00&&!c01&&!c10&&!c11;
}
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
scanf("%s%s",s+1,t+1);
fac[0]=1;
for(int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
inv[N-1]=qp(fac[N-1],mod-2);
for(int i=N-2;~i;i--) inv[i]=mul(inv[i+1],i+1);
int c00,c01,c10,c11;
read(c00),read(c01),read(c10),read(c11);
int ans=((cal(c00,c01,c10,c11,t)-cal(c00,c01,c10,c11,s)+ck(c00,c01,c10,c11,t))%mod+mod)%mod;
printf("%d\n",ans);
return 0;
}
2019年6月2日