题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4733
题目大意:
定义G(x)=x⊕(x>>1).给两个由0、1、?组成的长度相同的字符串S1,S2.其中?表示0、1状态不确定,求有多少种p,使得G(p)=S1,G(p+1)=S2
如果p唯一,则输出G(p)和G(p+1)(注意这中间不能有问号)。
解题思路:
这是我写的史上最臭最长最戳的代码,大神请跳过。
分析函数G(x)=x⊕(x>>1) 也就是右移一位再抑或,从高位出发,构造p和p+1串,先分别放一个0到p和p+1(右移高位时补零的),然后根据S1和S2的状态以及p和p+1的前一状态构造出当前的p和p+1状态,
构造方法:
若S='0'则当前的p和前一位p相同,否则相反(0《-》1)
如果S='?',则可以尝试00 01 10 11四种状态。
再来分析p和p+1的特点。
1、最低位肯定不一样。
2、除最后一位外,前面每一位要么相同,要么p<p+1,如果前面某一位p<p+1(也就是01),后面的p一定全部为1,后面p+1一定全部为0.
综合G(x)和p与p+1的特点,可以构造dp状态,
dp[i][j][0][len]:表示当p的第len位为i,p+1的第len位为j,且p<q时的总数。
dp[i][j][1][len]:表示当p的第len位为i,p+1的第len位为j,且p=q时的总数。
根据当前的S和前面一位的状态可以递推出当前的位的P和p+1。
注意:
1、最后一位要单独处理。(01或10)
2、只有一种的情况时要记录路径 ,把S中的?确定下来。
比如? ? 答案为0,1而不是?,?
代码:
#include<iostream> #include<cmath> #include<cstdio> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #define eps 1e-6 #define INF 0x3fffffff #define PI acos(-1.0) #define ll __int64 #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 110000 #define M 1000000007 //分别记录达到该状态时的上一状态的第一串和第二串的值,以及是否相等的状态 int path1[2][2][2][Maxn],path2[2][2][2][Maxn],path3[2][2][2][Maxn]; int dp[2][2][2][Maxn]; char sa1[Maxn],sa2[Maxn]; char ans1[Maxn],ans2[Maxn]; int main() { int tt; scanf("%d",&tt); for(int ca=1;ca<=tt;ca++) { scanf("%s%s",sa1+1,sa2+1); int len=strlen(sa1+1); memset(dp,-1,sizeof(dp)); path2[0][0][1][0]=path1[0][0][1][0]=-1; path3[0][0][1][0]=-1; int la1=0,la2=0; dp[0][0][1][0]=1; //第三维1表示相等 0表示小于 for(int i=1;i<=len;i++) { if(sa1[i]!='?'&&sa2[i]!='?') { for(int la1=0;la1<=1;la1++) for(int la2=0;la2<=1;la2++) { int p,q; p=(sa1[i]=='0')?(la1):(la1^1); //构造出当前状态 q=(sa2[i]=='0')?(la2):(la2^1); for(int t=0;t<=1;t++) { if(dp[la1][la2][t][i-1]==-1)//前面状态无效 continue; if(i==len) //最后一位单独处理 { if(p==q) //最后一位只能是0、1或者1,0 continue; if(p) //P串中为1时,P+1串肯定为0 { if(!t) //并且前面P<P+1 { if(dp[p][q][1][len]==-1) dp[p][q][1][len]=dp[la1][la2][0][len-1]; else dp[p][q][1][len]+=dp[la1][la2][0][len-1]; dp[p][q][1][len]%=M; path1[p][q][1][len]=la1; path2[p][q][1][len]=la2; path3[p][q][1][len]=t; } } else //为0 1 { if(t) //前面必须相等 { if(dp[p][q][1][len]==-1) dp[p][q][1][len]=dp[la1][la2][0][len-1]; else dp[p][q][1][len]+=dp[la1][la2][0][len-1]; dp[p][q][1][len]%=M; path1[p][q][1][len]=la1; path2[p][q][1][len]=la2; path3[p][q][1][len]=t; } } continue; } if(!t) //小于的情况 { if(p!=1||q!=0) //P 必须为1 P+1必须为0 continue; if(dp[p][q][t][i]==-1) dp[p][q][t][i]=dp[la1][la2][t][i-1]; else dp[p][q][t][i]+=dp[la1][la2][t][i-1]; dp[p][q][t][i]%=M; path1[p][q][t][i]=la1; path2[p][q][t][i]=la2; path3[p][q][t][i]=t; } else //等于的情况 { if(p>q) //这种情况不存在 continue; if(dp[la1][la2][t][i-1]==-1) continue; if(p<q) //0,1 当前小于 { if(dp[p][q][0][i]==-1) dp[p][q][0][i]=dp[la1][la2][t][i-1]; else dp[p][q][0][i]+=dp[la1][la2][t][i-1]; dp[p][q][0][i]%=M; path1[p][q][0][i]=la1; path2[p][q][0][i]=la2; path3[p][q][0][i]=t; } else //等于 { if(dp[p][q][1][i]==-1) dp[p][q][1][i]=dp[la1][la2][t][i-1]; else dp[p][q][1][i]+=dp[la1][la2][t][i-1]; dp[p][q][1][i]%=M; path1[p][q][1][i]=la1; path2[p][q][1][i]=la2; path3[p][q][1][i]=t; } } } } } else if(sa1[i]=='?'&&sa2[i]=='?') { for(int la1=0;la1<=1;la1++) for(int la2=0;la2<=1;la2++) { for(int t=0;t<=1;t++) { if(dp[la1][la2][t][i-1]==-1) continue; if(i==len) { if(t) //相等,最后一位只能是0 1 { if(dp[0][1][1][len]==-1) dp[0][1][1][len]=dp[la1][la2][t][len-1]; else dp[0][1][1][len]+=dp[la1][la2][t][len-1]; dp[0][1][1][len]%=M; path1[0][1][1][i]=la1; path2[0][1][1][i]=la2; path3[0][1][1][i]=t; } else // 1 0 前面小于 { if(dp[1][0][1][len]==-1) dp[1][0][1][len]=dp[la1][la2][t][len-1]; else dp[1][0][1][len]+=dp[la1][la2][t][len-1]; dp[1][0][1][len]%=M; path1[1][0][1][i]=la1; path2[1][0][1][i]=la2; path3[1][0][1][i]=t; } continue; } if(!t) //小于 必须1,0 { if(dp[1][0][0][i]==-1) dp[1][0][0][i]=dp[la1][la2][t][i-1]; else dp[1][0][0][i]+=dp[la1][la2][t][i-1]; dp[1][0][0][i]%=M; path1[1][0][0][i]=la1; path2[1][0][0][i]=la2; path3[1][0][0][i]=t; } else //等于 可以继续等于 也可以当前位小于 { if(dp[0][0][1][i]==-1) dp[0][0][1][i]=dp[la1][la2][t][i-1]; else dp[0][0][1][i]+=dp[la1][la2][t][i-1]; dp[0][0][1][i]%=M; path1[0][0][1][i]=la1; path2[0][0][1][i]=la2; path3[0][0][1][i]=t; if(dp[1][1][1][i]==-1) dp[1][1][1][i]=dp[la1][la2][t][i-1]; else dp[1][1][1][i]+=dp[la1][la2][t][i-1]; dp[1][1][1][i]%=M; path1[1][1][1][i]=la1; path2[1][1][1][i]=la2; path3[1][1][1][i]=t; if(dp[0][1][0][i]==-1) dp[0][1][0][i]=dp[la1][la2][t][i-1]; else dp[0][1][0][i]+=dp[la1][la2][t][i-1]; dp[0][1][0][i]%=M; path1[0][1][0][i]=la1; path2[0][1][0][i]=la2; path3[0][1][0][i]=t; } } } } else if(sa1[i]=='?') { for(int la1=0;la1<=1;la1++) for(int la2=0;la2<=1;la2++) { for(int t=0;t<=1;t++) { if(dp[la1][la2][t][i-1]==-1) continue; int q=(sa2[i]=='0')?(la2):(la2^1); if(i==len) { if(q) //0 1 { if(t) //等于 { if(dp[0][1][1][len]==-1) dp[0][1][1][len]=dp[la1][la2][t][len-1]; else dp[0][1][1][len]+=dp[la1][la2][t][len-1]; dp[0][1][1][len]%=M; path1[0][1][1][i]=la1; path2[0][1][1][i]=la2; path3[0][1][1][i]=t; } } else // 1 0 { if(!t) //小于 { if(dp[1][0][1][len]==-1) dp[1][0][1][len]=dp[la1][la2][t][len-1]; else dp[1][0][1][len]+=dp[la1][la2][t][len-1]; dp[1][0][1][len]%=M; path1[1][0][1][i]=la1; path2[1][0][1][i]=la2; path3[1][0][1][i]=t; } } continue; } if(!t) //小于 当前必须1 0 { if(q) continue; if(dp[1][0][0][i]==-1) dp[1][0][0][i]=dp[la1][la2][t][i-1]; else dp[1][0][0][i]+=dp[la1][la2][t][i-1]; dp[1][0][0][i]%=M; path1[1][0][0][i]=la1; path2[1][0][0][i]=la2; path3[1][0][0][i]=t; } else //等于 当前可以等于也可以小于 { if(dp[q][q][1][i]==-1) dp[q][q][1][i]=dp[la1][la2][t][i-1]; else dp[q][q][1][i]+=dp[la1][la2][t][i-1]; dp[q][q][1][i]%=M; path1[q][q][1][i]=la1; path2[q][q][1][i]=la2; path3[q][q][1][i]=t; if(!q) continue; if(dp[0][1][0][i]==-1) dp[0][1][0][i]=dp[la1][la2][t][i-1]; else dp[0][1][0][i]+=dp[la1][la2][t][i-1]; dp[0][1][0][i]%=M; path1[0][1][0][i]=la1; path2[0][1][0][i]=la2; path3[0][1][0][i]=t; } } } } else //sa2[i]=='?' { for(int la1=0;la1<=1;la1++) for(int la2=0;la2<=1;la2++) { for(int t=0;t<=1;t++) { if(dp[la1][la2][t][i-1]==-1) continue; int p=(sa1[i]=='0')?(la1):(la1^1); if(i==len) { if(p) { if(!t) { if(dp[1][0][1][len]==-1) dp[1][0][1][len]=dp[la1][la2][t][len-1]; else dp[1][0][1][len]+=dp[la1][la2][t][len-1]; dp[1][0][1][len]%=M; path1[1][0][1][i]=la1; path2[1][0][1][i]=la2; path3[1][0][1][i]=t; } } else //p==0 { if(t) { if(dp[0][1][1][len]==-1) dp[0][1][1][len]=dp[la1][la2][t][len-1]; else dp[0][1][1][len]+=dp[la1][la2][t][len-1]; dp[0][1][1][len]%=M; path1[0][1][1][i]=la1; path2[0][1][1][i]=la2; path3[0][1][1][i]=t; } } continue; } if(!t) { if(!p) continue; if(dp[1][0][0][i]==-1) dp[1][0][0][i]=dp[la1][la2][t][i-1]; else dp[1][0][0][i]+=dp[la1][la2][t][i-1]; dp[1][0][0][i]%=M; path1[1][0][0][i]=la1; path2[1][0][0][i]=la2; path3[1][0][0][i]=t; } else { if(dp[p][p][1][i]==-1) dp[p][p][1][i]=dp[la1][la2][t][i-1]; else dp[p][p][1][i]+=dp[la1][la2][t][i-1]; dp[p][p][1][i]%=M; path1[p][p][1][i]=la1; path2[p][p][1][i]=la2; path3[p][p][1][i]=t; if(p) continue; if(dp[0][1][0][i]==-1) dp[0][1][0][i]=dp[la1][la2][t][i-1]; else dp[0][1][0][i]+=dp[la1][la2][t][i-1]; dp[0][1][0][i]%=M; path1[0][1][0][i]=la1; path2[0][1][0][i]=la2; path3[0][1][0][i]=t; } } } } // for(int k=0;k<=1;k++) // for(int kk=0;kk<=1;kk++) // printf("dp[%d][%d][0][%d]:%d ",k,kk,i,dp[k][kk][0][i]),printf("dp[%d][%d][1][%d]:%d\n",k,kk,i,dp[k][kk][1][i]);; } int ans=0; int a,b,tmp; if(dp[0][1][1][len]!=-1) { ans=(ans+dp[0][1][1][len])%M; a=0,b=1,tmp=1; } if(dp[1][0][1][len]!=-1) { ans=(ans+dp[1][0][1][len])%M; a=1,b=0,tmp=1; } printf("Case #%d:\n",ca); if(ans==1) { sa1[len]=a+'0',sa2[len]=b+'0'; //输出路径 int i=len-1; while(i>=1) { int aa=path1[a][b][tmp][i+1]; int bb=path2[a][b][tmp][i+1]; int tmm=path3[a][b][tmp][i+1]; sa1[i]=aa+'0'; sa2[i]=bb+'0'; a=aa,b=bb,tmp=tmm; i--; } //先求出P 和 P+1 然后求出G(p)和G(p+1) // printf("%s\n%s\n",sa1+1,sa2+1); sa1[0]=sa2[0]='0'; for(int i=1;i<=len;i++) { ans1[i]=(sa1[i]==sa1[i-1])?'0':'1'; ans2[i]=(sa2[i]==sa2[i-1])?'0':'1'; } ans1[len+1]=ans2[len+1]='\0'; printf("%s\n%s\n",ans1+1,ans2+1); } else if(ans==0) printf("Impossible\n"); else printf("Ambiguous %d\n",ans); } return 0; }