题 目 描 述 题目描述 题目描述
求 整 数 对 A , B 的 个 数 , 满 足 求整数对 A,B 的个数,满足 求整数对A,B的个数,满足
a ≤ A ≤ b a\le A\le b a≤A≤b
c ≤ B ≤ d c\le B\le d c≤B≤d
A + B = A ⊕ B . A+B=A\oplus B. A+B=A⊕B.
其 中 ⊕ 表 示 按 位 异 或 。 其中 \oplus 表示按位异或。 其中⊕表示按位异或。
输 入 格 式 输入格式 输入格式
四 个 二 进 制 整 数 a , b , c , d 四个二进制整数 a,b,c,d 四个二进制整数a,b,c,d
可 能 有 前 导 零 , 但 每 个 整 数 的 位 数 可能有前导零, 但每个整数的位数 可能有前导零,但每个整数的位数 ≤ 1 0 7 \leq10^7 ≤107
.
输 出 格 式 输出格式 输出格式
一 行 , 一 个 整 数 , 答 案 一行,一个整数,答案 一行,一个整数,答案 m o d ( 1 0 9 + 7 ) mod\,(10^9+7) mod(109+7)
样 例 样例 样例
样 例 输 入 1 样例输入1 样例输入1
1111011 1111011 1111011
1000100010 1000100010 1000100010
1010011010 1010011010 1010011010
1100010101 1100010101 1100010101
样 例 输 出 1 样例输出1 样例输出1
2126 2126 2126
样 例 输 入 2 样例输入2 样例输入2
11110000011110011 11110000011110011 11110000011110011
1101111011100001000 1101111011100001000 1101111011100001000
11000000110100011101 11000000110100011101 11000000110100011101
100110001001011001111111 100110001001011001111111 100110001001011001111111
样 例 输 出 2 样例输出2 样例输出2
620469990 620469990 620469990
来 源 来源 来源
l r e lre lre
题 解 : 题解: 题解:
裸 数 位 D P 裸数位DP 裸数位DP
暴 力 讨 论 暴力讨论 暴力讨论
上 板 子 上板子 上板子
#include
#define N 10000007
using namespace std;
const long long mod=1e9+7;
long long f[2][2][2][2],g[2][2][2][2];
char aa[N],bb[N],cc[N],dd[N];
int a[N],b[N],c[N],d[N];
long long work(int lt,int *x,int *y){
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
f[1][1][0][0]=1;
for(int i=1;i<=lt;++i){
long long xuyu=0,xuyd=0,xdyu=0,xdyd=0;
//up 顶边界 down 不顶边界
for(int j=0;j<=1;++j){
for(int k=0;k<=1;++k){
if(j==1&&k==1)continue;
xuyu+=f[1][1][j][k];
xuyd+=f[1][0][j][k];
xdyu+=f[0][1][j][k];
xdyd+=f[0][0][j][k];
}
}
for(int j=0;j<=1;++j){
for(int k=0;k<=1;++k){
if(j==1&&k==1)continue;
g[0][0][j][k]+=xdyd;
}
}
if(x[i]==1&&y[i]==1){
g[0][0][0][0]+=xuyu+xuyd+xdyu;
g[0][0][1][0]+=xdyu;
g[0][0][0][1]+=xuyd;
g[1][0][1][0]+=xuyu+xuyd;
g[0][1][0][1]+=xdyu+xuyu;
}
if(x[i]==1&&y[i]==0){
g[0][0][0][0]+=xuyd;
g[0][0][1][0]+=0;
g[0][0][0][1]+=xuyd;
g[1][0][1][0]+=xuyd;
g[0][1][0][0]+=xuyu+xdyu;
g[0][1][1][0]+=xdyu;
g[1][1][1][0]+=xuyu;
}
if(x[i]==0&&y[i]==1){
g[0][0][0][0]+=xdyu;
g[0][0][1][0]+=xdyu;
g[0][0][0][1]+=0;
g[1][0][0][0]+=xuyu+xuyd;
g[1][0][0][1]+=xuyd;
g[0][1][0][1]+=xdyu;
g[1][1][0][1]+=xuyu;
}
if(x[i]==0&&y[i]==0){
g[0][0][0][0]+=0;
g[1][0][0][0]+=xuyd;
g[1][0][0][1]+=xuyd;
g[0][1][0][0]+=xdyu;
g[0][1][1][0]+=xdyu;
g[1][1][0][0]+=xuyu;
}
for(int j=0;j<=1;j++){
for(int k=0;k<=1;++k){
for(int h=0;h<=1;++h){
for(int l=0;l<=1;++l){
if(h==1&&l==1)continue;
f[j][k][h][l]=g[j][k][h][l]%mod;
memset(g,0,sizeof(g));
}
long long ans=0;
for(int j=0;j<=1;j++){
for(int k=0;k<=1;++k){
for(int h=0;h<=1;++h){
for(int l=0;l<=1;++l){
if(h==1&&l==1)continue;
ans=(ans+f[j][k][h][l])%mod;
}
}
}
}
return ans;
}
int main(){
scanf("%s%s%s%s",aa,bb,cc,dd);
int la=strlen(aa),lb=strlen(bb),lc=strlen(cc),ld=strlen(dd),lt=max(max(la,lb),max(lc,ld));
for(int i=1;i<=lt;++i){
if(la>=lt-i+1)a[i]=aa[i-(lt-la+1)]-'0';
if(lb>=lt-i+1)b[i]=bb[i-(lt-lb+1)]-'0';
if(lc>=lt-i+1)c[i]=cc[i-(lt-lc+1)]-'0';
if(ld>=lt-i+1)d[i]=dd[i-(lt-ld+1)]-'0';
}
long long ans=0;
int flaga=0,flagc=0;
ans=work(lt,b,d);
for(int i=lt;i>=1;--i){
if(a[i]==1){
a[i]=0;flaga=1;break;
}else{
a[i]=1;
}
}
for(int i=lt;i>=1;--i){
if(c[i]==1){
c[i]=0;flagc=1;break;
}else{
c[i]=1;
}
}
if(flaga&&flagc){
ans=(ans-work(lt,a,d)-work(lt,b,c)+work(lt,a,c))%mod;
}
if(flaga&&flagc==0){
ans=(ans-work(lt,a,d))%mod;
}
if(flaga==0&&flagc){
ans=(ans-work(lt,b,c))%mod;
}
printf("%lld\n",(ans+mod)%mod);
return 0;
}
/*
00
00
00
10
*/