Hdu 5456 Matches Puzzle Game

問有多少個等式滿足使用的火柴棍個數恰好爲n

輸出等式個數(modm)

5n500,3m2×109


就是求滿足a+b=c ,並且a,b,c 每一位按照使用的火柴棍個數加權之後恰好等於n3 的等式個數

考慮到這個題的狀態和之前使用了多少位無關並且保證剩下的火柴棍是單調遞減的

可以記dpcnt,cry,az,bz,cz 爲火柴棍還有cnt 個,下一位是否要進位,abc 是否都是前導零的方案數


因爲剛開始把位數記錄到了狀態裏,在TLE 的時候把az,bz,cz 壓到了一個數用二進制表示了。其實本質還是一樣的

#include<bits/stdc++.h>
using namespace std;

const int v[10] = {6,2,5,5,4,5,6,3,7,6};
#define LL int 
const int maxn = 550;

LL m;
LL dp[2][maxn][8];

LL dfs(bool cry,int left,int bnd){
    if(left <= 0) return left == 0 && !cry && !bnd; 
    LL & ndp = dp[cry][left][bnd];
    if(~ndp) return ndp;
    ndp = 0;
    for(int i=0;i<=9;i++){
        for(int j=0;j<=9;j++){
            for(int t=0;t<=1;t++){
                int s = i + j + t;
                int nsta = bnd;
                nsta &= (i==0)<<0 | 6;
                nsta &= (j==0)<<1 | 5;
                nsta &= (s==0)<<2 | 3;
                int nleft = left - (!((nsta>>0)&1)) * v[i]
                                 - (!((nsta>>1)&1)) * v[j]
                                 - (!((nsta>>2)&1)) * v[s%10];
                if(nleft < 0) continue;
                if((s > 9) == cry)
                    ndp = (dfs(t
                               ,nleft
                               ,nsta) + 0ll + ndp) % m;
            }
        }
    }
    return ndp;
}

LL cal(int n){
    memset(dp,-1,sizeof(dp));
    return dfs(false,n-3,7);
}
int main(){
    int T,icase = 1;
    scanf("%d",&T);
    int n;
    while(T-- && ~scanf("%d %d",&n,&m)){
        printf("Case #%d: %d\n",icase++,cal(n));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章