Bzoj1072--Scoi2007排列perm

一开始sb以为是数位dp,想到状态是十维每维代表每个数字出现次数,再加一维代表余数。空间时间都要炸飞。。。

后来想了想可以直接用数字在原串上出现的位置来代替那十维,结果没有意识到这就是状压dp。。。导致写出来常数爆炸

不过过了就懒得改了。- -

代码看看就可以了:

#include<bits/stdc++.h>
#define LL long long
#define MAXN 20000005
using namespace std;

int dp[15][1030][1005],d,T;
int len,full;
char s[15];

int check(int v,int st) {
    for(int i=0;i<len;i++) {
        if(s[i]==v&&!(st&(1<<i))) return i;
    }
    return -1;
}

int mdp() {
    for(int t,i=0;i<=9;i++) {
        if((t=check(i+'0',0))!=-1) dp[1][1<<t][i%d]++;
    }
    for(int i=2;i<=len;i++) {
        for(int st=0;st<full;st++) 
            for(int k=0;k<d;k++) {
                if(!dp[i-1][st][k]) continue;
                for(int t,j=0;j<=9;j++) {
                    if((t=check(j+'0',st))!=-1) dp[i][st|(1<<t)][(k*10+j)%d]+=dp[i-1][st][k];
                }
            }
    }
    return dp[len][full-1][0];
}

int main() {
    scanf("%d",&T);
    for(int i=1;i<=T;i++) {
        scanf("%s%d",s,&d);
        memset(dp,0,sizeof(dp));
        len=strlen(s);full=1<<len;
        printf("%d\n",mdp());
    }
    return 0;
}

 

posted @ 2016-10-10 18:38  ihopenot  阅读(157)  评论(0编辑  收藏  举报