传送门
解析:
这个数位DP是 O ( l e n ) O(len) O(len)的。。。
只需要预处理组合数就行了。。。
思路:
首先注意到几个性质。
1.
c
0
,
1
+
1
≥
c
1
,
0
≥
c
0
,
1
c_{0,1}+1≥c_{1,0}≥c_{0,1}
c0,1+1≥c1,0≥c0,1这个很显然,因为
1
/
0
1/0
1/0区间的出现是交替的。
2.
c
1
,
0
+
c
0
,
0
c_{1,0}+c_{0,0}
c1,0+c0,0是0出现的次数。考虑统计每个串中靠后的0。
3.
c
0
,
1
+
c
1
,
1
+
1
c_{0,1}+c_{1,1}+1
c0,1+c1,1+1 是1出现的次数。考虑统计每个串中靠后的1和开头的1。
c 1 , 0 c_{1,0} c1,0实际上是全 0 0 0区间的个数,同理 c 0 , 1 + 1 c_{0,1}+1 c0,1+1实际上是全1区间的个数。
如果我们的限制只有长度那就好了,直接上球盒问题就可以做了。
但是有上界的限制。。。
没关系,我们只需要处理前缀和它的相同,某一位开始比它小的情况,那么后面就可以乱填了。
其实就是处理在某一位为 1 1 1的地方填 0 0 0,后面就可以球盒问题乱搞了。
注意一下要判断我们强制填 0 0 0的这个地方是同前面的0同属于一个盒子还是需要重新分配一个盒子。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
cs ll mod=1000000007;
cs int N=100005;
int fac[N],inv[N],ifac[N];
inline int C(int n,int m){
return (ll)fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
inline int calc(int n,int m){
if(m>n)return 0;
if(m==0)return n==0;
return C(n-1,m-1);
}
string l,r;
int c[2][2],tot=1;
inline int solve(cs string &a){
if(a.size()-1<tot||(c[0][1]+1!=c[1][0]&&c[1][0]!=c[0][1]))return 0;
if(a.size()-1>tot)return 1ll*calc(c[0][1]+c[1][1]+1,c[0][1]+1)*calc(c[1][0]+c[0][0],c[1][0])%mod;
int ans=0,t1=0,t0=0,cnt1=0,cnt0=0;
for(int re i=1;i<=tot;++i){
if(a[i]^a[i-1])(a[i]=='1')?++t1:++t0;
(a[i]=='1')?++cnt1:++cnt0;
if(t1>c[0][1]+1||t0>c[1][0]||cnt1>c[1][1]+c[0][1]+1||cnt0>c[0][0]+c[1][0])break;
if(a[i+1]=='1'){
int res0=c[0][0]+c[1][0]-cnt0,res1=c[1][1]+c[0][1]+1-cnt1;
int rest0=c[1][0]-t0-(a[i]!='0')+1,rest1=c[0][1]+1-t1;
ans=(1ll*ans+1ll*calc(res1,rest1)*calc(res0,rest0)%mod)%mod;
}
else if(i==tot&&cnt0==c[0][0]+c[1][0]&&cnt1==c[1][1]+c[0][1]+1&&t0==c[1][0]&&t1==c[0][1]+1)++ans;
}
return ans%mod;
}
signed main(){
fac[0]=fac[1]=ifac[0]=ifac[1]=inv[0]=inv[1]=1;
for(int re i=2;i<=100000;++i){
fac[i]=1ll*fac[i-1]*i%mod;
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
}
cin>>l>>r;l=" "+l;r=" "+r;
for(int re i=0;i<2;++i)
for(int re j=0;j<2;++j)scanf("%d",&c[i][j]),tot+=c[i][j];
int ans=(solve(r)-solve(l)+mod)%mod;
for(int re i=2;i<l.size();++i)--c[l[i-1]^48][l[i]^48];
if(!c[0][0]&&!c[1][0]&&!c[1][1]&&!c[0][1])++ans;
cout<<ans%mod<<endl;
return 0;
}