Lightoj 1158【记忆化+状压DP】

来源:互联网 发布:linux修改nice值 编辑:程序博客网 时间:2024/05/16 05:09

思路:
以前还对取膜余数挺敏感的,现在好菜啊!
DP[ i ][ j ]代表在状态i下,这个状态%d=j值的个数。
那么不就是个状压DP呀!啪啪啪敲!

memset(dp, 0, sizeof(dp));    int Max = (1<<n) - 1;    dp[0][0] = 1;    for(int i=0;i<=Max;i++){        for(int k=0;k<mod;k++){            for(int j=0;j<n;j++){                if(i & (1<<j)) continue;                dp[i|(1<<j)][(k*10+(s[j]-'0')) % mod] += dp[i][k];            }        }    }    return dp[Max][0];

恭喜~TLE
记忆化,AC~

#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<queue>#include<vector>#include<map>#include<set>#include<algorithm>#include<list>using namespace std;typedef pair<int,int> PII;typedef long long LL;#define mem(a, b) memset(a, b, sizeof(a))#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1const double eps = 1e-9;const double pi = acos(-1.0);const int INF = 0x3f3f3f3f;const int Maxn = 2e5 + 10;int mod, n;char s[15];int num[12];int f[15];int dp[1<<11][1010];int DFS(int mask, int isDiv){    if(mask == (1<<n) - 1) return (isDiv == 0);    int &res = dp[mask][isDiv];    if(res != -1) return res;    res = 0;    for(int i=0;i<n;i++){        if(mask & (1<<i)) continue;        res = res + DFS(mask|(1<<i), ((isDiv*10)+(s[i]-'0'))%mod);    }    return res;}//int solve(){//    memset(dp, 0, sizeof(dp));//    int Max = (1<<n) - 1;//    dp[0][0] = 1;//    for(int i=0;i<=Max;i++){//        for(int k=0;k<mod;k++){//            for(int j=0;j<n;j++){//                if(i & (1<<j)) continue;//                dp[i|(1<<j)][(k*10+(s[j]-'0')) % mod] += dp[i][k];//            }//        }//    }//    return dp[Max][0];//}int main(){    f[0] = 1;    for(int i=1;i<=10;i++) f[i] = f[i-1] * i;    int x;    int T, cas = 1;    scanf("%d", &T);    while(T--){        scanf("%s%d", &s, &mod);        memset(num, 0, sizeof(num));        n = strlen(s);        for(int i=0;i<n;i++){            x = s[i] - '0';            num[x]++;        }        memset(dp, -1, sizeof(dp));        int ans = DFS(0, 0);//        int ans = solve();        for(int i=0;i<10;i++) ans = ans / f[num[i]];        printf("Case %d: %d\n", cas++, ans);    }    return 0;}