#4674. and

题 目 描 述 题目描述
求 整 数 对 A , B 的 个 数 , 满 足 求整数对 A,B 的个数,满足 A,B

a ≤ A ≤ b a\le A\le b aAb

c ≤ B ≤ d c\le B\le d cBd

A + B = A ⊕ B . A+B=A\oplus B. A+B=AB.

其 中 ⊕ 表 示 按 位 异 或 。 其中 \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
*/

你可能感兴趣的:(动态规划--数位DP)