LightOJ1158 Anagram Division(状压DP)

题目问一个数字字符串的不重复全排列有几个能被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 }

 

转载于:https://www.cnblogs.com/WABoss/p/5176472.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值