BZOJ 1072: [SCOI2007]排列perm

来源:互联网 发布:什么命令linux死机 编辑:程序博客网 时间:2024/05/16 07:07

点这里!!!>_<
PO姐的blog很详尽>o<


第一次写状压DP,不知道怎么下手,所以只能看题解了(>_<~~~~)


代码如下:(只是多了几行注释)

#include<algorithm>//1023---1111111111,1024---1<<10 #include<iostream>#include<cstring>#include<cstdio>using namespace std;int t,n,d,ans,f[1<<10][1<<10],digit[1<<10],tens[15],cnt[15],factorial[15];char s[15];int Get(int x){    int res=0;    while(x)        res+=x&1,x>>=1;    return res;}int main(){    factorial[0]=1,tens[0]=1;//factorial代表i的阶乘     for(int i=1;i<=10;i++)        factorial[i]=factorial[i-1]*i,tens[i]=tens[i-1]*10;    for(int i=0;i<1<<10;i++)        digit[i]=Get(i);//digit[i]=j代表十进制为i的数字转化成二进制有多少位1    scanf("%d",&t);    while(t--){        scanf("%s%d",s,&d);        memset(f,0,sizeof(f)),memset(cnt,0,sizeof(cnt));        f[0][0]=1,n=strlen(s);        for(int i=1;i<1<<n;i++){            for(int j=0;j<n;j++)                if(1<<j&i){                    int temp=tens[digit[i]-1]%d*(s[j]-'0')%d;                    for(int k=0;k<d;k++)                        f[i][(k+temp)%d]+=f[1<<j^i][k];                }        }        ans=f[(1<<n)-1][0];//转化成二进制有n个1---这n个数全部选择,余数为0         for(int i=0;i<n;i++)            cnt[s[i]-'0']++;        for(int i=0;i<=9;i++)//一定要记得从0开始>o<             ans/=factorial[cnt[i]];//多重集的性质,(n1+n2+......+na)!/(n1!n2!......na!)         cout<<ans<<endl;     }    return 0;}

by >o< neighthorn

1 0