這是個狀態DP 首先我們設p的的二進制爲 a1 a2 a3 a4 a5 a6 明顯[p/2] 爲 0 a1 a2 a3 a4 a5 然後我們設a3爲p第一個爲0的位數那麼p就是a1 a2 0 1 1 [p/2]= 爲 0 a1 a2 01 明顯g(x) 爲 a1 a2^a1 a2 1 0 0
明顯p+1 的二進制爲 a1 a2 1 0 0 ,[p+1/2]爲 0 a1 a2 1 0 g(p) 爲a1 a1^a2 ~a3 1 0 從上面公式可以看出 str1 str2 應該只有1個位置不同,而且不同後(如果後面還厚位數),一定要爲1,1以後就只能全是0 了,
但是 你會發現 1001 1011 這個不成立,這個說明前面相同的位數應該滿足某些性質,如果我們設g(p)爲b1 b2 b3 b4 b5 ....得b1=a1 b2=a1^a2 b3=a2^a3 後發現如果第3位不同明顯要滿足b3=b1^b2^b3 所以b1^b2=0所以明顯前面應該滿足某些要求 就像 1001 1011 明顯 b1^b2!=0 所以不成立
後面dp[i][j][k][3]表示第i(1-100000)位的時候取j(0-1)前面爲^和爲k是的3種狀態
0狀態表示還沒有不同
1狀態表示已經有不同了下一個需要1
2表示已經有1了後面只能有全0了
送上代碼 寫的比較戳(答案爲1的時候需要記錄路徑) 140行卻有5000b
#include<cstdio>
#include<cstring>
#define M 100010
#define N 1000000007
int dp[M][2][2][3];
char str1[M];
char str2[M];
int s(char p){
if(p=='1') return 1;
return 0;
}
int e(char p){
if(p=='0') return 0;
return 1;
}
int pre[M*40][2];
int change(int x,int y,int z,int u){
return x*12+y*6+z*3+u;
}
int ans[M];
void pf(int n1,int n){
if(n1==0){
puts("Impossible");
}
else if(n1>1){
printf("Ambiguous %d\n",n1);
}
else{
int len=n;
int flag=0;
int t1=0 ;
if(dp[n][0][0][1]==1){
t1=change(n,0,0,1);
}
else if(dp[n][0][0][2]==1){
t1=change(n,0,0,2);
}
else if(dp[n][1][0][1]==1){
t1=change(n,1,0,1);
}
else if(dp[n][1][0][2]==1){
t1=change(n,1,0,2);
}
while(len>0){
ans[len--]=pre[t1][1];
t1=pre[t1][0];
}
for(int i=1;i<=n;i++){
if(ans[i]<30){
printf("%d",ans[i]);
}
else{
printf("%d",ans[i]-30);
}
}
puts("");
for(int i=1;i<=n;i++){
if(ans[i]<30){
printf("%d",ans[i]);
}
else{
printf("%d",!(ans[i]-30));
}
}
puts("");
}
}
int main(){
int cas;
while(~scanf("%d",&cas)){
for(int q=1;q<=cas;q++){
scanf("%s",str1);
scanf("%s",str2);
memset(dp,0,sizeof(dp));
dp[0][0][0][0]=1;
int n=strlen(str1);
for(int i=0;i<n;i++){
for(int j=0;j<2;j++){
for(int k=0;k<2;k++){
for(int w=0;w<3;w++){
if(dp[i][j][k][w]<1) continue;
for(int j1=s(str1[i]);j1<=e(str1[i]);j1++){
for(int k1=s(str2[i]);k1<=e(str2[i]);k1++){
if(w==0){
if(j1==k1){
int t1=k^j1;
dp[i+1][j1][t1][0]+=dp[i][j][k][w];
dp[i+1][j1][t1][0]%=N;
int flag1=change(i,j,k,w);
int flag2=change(i+1,j1,t1,0);
pre[flag2][0]=flag1;
pre[flag2][1]=j1;
}
if(j1!=k1){
if(j1==k){
dp[i+1][j1][0][1]+=dp[i][j][k][w];
dp[i+1][j1][0][1]%=N;
int flag1=change(i,j,k,w);
int flag2=change(i+1,j1,0,1);
pre[flag2][0]=flag1;
pre[flag2][1]=j1+30;
}
}
}
else if(w==1){
if(j1==k1&&j1==1){
dp[i+1][j1][0][2]+=dp[i][j][k][w];
dp[i+1][j1][0][2]%=N;
int flag1=change(i,j,k,w);
int flag2=change(i+1,j1,0,2);
pre[flag2][0]=flag1;
pre[flag2][1]=j1;
}
}
else if(w==2){
if(j1==k1&&j1==0){
dp[i+1][j1][0][2]+=dp[i][j][k][w];
dp[i+1][j1][0][2]%=N;
int flag1=change(i,j,k,w);
int flag2=change(i+1,j1,0,2);
pre[flag2][0]=flag1;
pre[flag2][1]=j1;
}
}
}
}
}
}
}
}
int tsum=0;
for(int j=0;j<2;j++){
tsum+=dp[n][j][0][1];
tsum%=N;
tsum+=dp[n][j][0][2];
tsum%=N;
}
printf("Case #%d:\n",q);
pf(tsum,n);
}
}
return 0;
}
c++能飄過!!