[bzoj1072][SCOI2007]排列(状态压缩DP)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1072
分析:看了题解才知道,状态的设计很巧妙,用余数表示,即f[i][j]表示二进制状态i下余数为j的方案数,然后列一列式子就可以了,注意排除相同数字的情况。
1 #include<cstring> 2 #include<algorithm> 3 #include<cstdio> 4 #include<string> 5 using namespace std; 6 const int maxn=1024; 7 int f[maxn+50][1000]; 8 char s[15]; 9 int t,d; 10 int main() 11 { 12 scanf("%d\n",&t); 13 while(t) 14 { 15 --t; 16 scanf("%s%d\n",s,&d); 17 int n=strlen(s); 18 memset(f,0,sizeof(f)); 19 int m=(1<<n) - 1; 20 for(int i=0;i<n;++i) f[1<<i][(s[i]-48)%d]=1; 21 for(int i=1;i<=m;++i) 22 for(int j=0;j<n;++j) 23 if((i&(1<<j))!= 0 && i-(1<<j)>=0) 24 for(int k=0;k<d;++k) 25 f[i][(10*k+(s[j]-48))%d]+=f[i-(1<<j)][k]; 26 for(int i=0;i<=9;++i) 27 { 28 int ans=0; 29 for(int j=0;j<n;++j) 30 if(s[j]-48==i) ++ans; 31 int c=1; 32 for(int j=2;j<=ans;++j) c*=j; 33 f[m][0]/=c; 34 } 35 printf("%d\n",f[m][0]); 36 } 37 return 0; 38 }