hdu 4733 G(x) 狀態dp

這是個狀態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++能飄過!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章