首页 > 其他 > 详细

LightOJ1158 Anagram Division(状压DP)

时间:2016-02-01 23:54:41      阅读:172      评论:0      收藏:0      [点我收藏+]

题目问一个数字字符串的不重复全排列有几个能被d整除。

  • dp[S][m]表示用字符集合S构成的%d为m的数字字符串个数
  • dp[0][0]=0
  • 我为人人转移,dp[S+{x}][(m*10+str[x]-‘0‘)%d]+=dp[S][m](x∉S)

最后的结果再除以各字符出现次数的阶乘就是答案了,即dp[2strlen-1][0]/(t[0]!*t[1]!*t[2]!*t[3]!*t[4]!*t[5]!*t[6]!*t[7]!*t[8]!*t[9]!)。

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int d[1<<10][1111],fact[11]={1};
 5 int main(){
 6     for(int i=1; i<11; ++i) fact[i]=fact[i-1]*i;
 7     int t,m;
 8     char str[1111];
 9     scanf("%d",&t);
10     for(int cse=1; cse<=t; ++cse){
11         scanf("%s%d",str,&m);
12         int n=strlen(str);
13         memset(d,0,sizeof(d));
14         d[0][0]=1;
15         for(int i=0; i<(1<<n)-1; ++i){
16             for(int j=0; j<m; ++j){
17                 if(d[i][j]==0) continue;
18                 for(int k=0; k<n; ++k){
19                     if((i>>k)&1) continue;
20                     d[i|(1<<k)][(j*10+str[k]-0)%m]+=d[i][j];
21                 }
22             }
23         }
24         int times[10]={0};
25         for(int i=0; i<n; ++i) ++times[str[i]-0];
26         for(int i=0; i<10; ++i){
27             d[(1<<n)-1][0]/=fact[times[i]];
28         }
29         printf("Case %d: %d\n",cse,d[(1<<n)-1][0]);
30     }
31     return 0;
32 }

 

LightOJ1158 Anagram Division(状压DP)

原文:http://www.cnblogs.com/WABoss/p/5176472.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!