bzoj1072: [SCOI2007]排列perm

1072: [SCOI2007]排列perm

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

  给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0)。例如123434有90种排列能
被2整除,其中末位为2的有30种,末位为4的有60种。

Input

  输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间用空格隔开。s保证只包含数字0, 1
, 2, 3, 4, 5, 6, 7, 8, 9.

Output

  每个数据仅一行,表示能被d整除的排列的个数。

Sample Input

7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29

Sample Output

1
3
3628800
90
3
6
1398

HINT

 

在前三个例子中,排列分别有1, 3, 3628800种,它们都是1的倍数。

【限制】

100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15

 

Source

 

暴力DFS:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6  
 7 int n,m,t,len,res,num[11],a[11],d;
 8 char s[20];
 9  
10 bool check(){
11     long long o=0;
12     for(int i=len;i>0;i--)
13         o=o*10+a[i];
14     if(o%d==0) return 1;
15     else return 0;
16 }
17  
18 int dfs(int x){
19     int ans=0;
20     if(x==len+1){
21         if(check())
22             return 1;
23         else return 0;
24     }
25     for(int i=0;i<10;i++)
26     if(num[i]>0){
27         a[x]=i;
28         num[i]--;
29         ans+=dfs(x+1);
30         num[i]++;
31     }
32     return ans;
33 }
34  
35 int main(){
36     scanf("%d",&t);
37     for(int ii=1;ii<=t;ii++){
38         res=0;
39         scanf("%s %d",s,&d);
40         len=strlen(s);
41         memset(num,0,sizeof(num));
42         for(int i=0;i<len;i++)
43             num[s[i]-'0']++;
44         res=dfs(1);
45         printf("%d\n",res);
46     }
47 }

 

状压DP:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6  
 7 int len,n,m,t,dp[1025][1008],tot[11],v[11],d,ex[11];
 8 char s[108];
 9  
10 void solve(){
11     memset(dp,0,sizeof(dp));
12     dp[0][0]=1;
13     for(int i=0;i<ex[len];i++)
14         for(int j=0;j<d;j++)
15             if(dp[i][j]){
16                 for(int k=0;k<len;k++)
17                     if((i&ex[k])==0)
18                         dp[i|ex[k]][(j*10+s[k]-'0')%d]+=dp[i][j];
19             }
20 }
21  
22 int main(){
23     scanf("%d",&t);
24     ex[0]=1;
25     for(int i=1;i<=10;i++) ex[i]=ex[i-1]*2;
26     while(t--){
27         scanf("%s %d",s,&d);
28         len=strlen(s);
29         for(int i=0;i<=10;i++) v[i]=1,tot[i]=0;
30         for(int i=0;i<len;i++){
31             int x=s[i]-'0';
32             tot[x]++;
33             v[x]*=tot[x];
34         }
35         solve();
36         for(int i=0;i<=9;i++) dp[ex[len]-1][0]/=v[i];
37         printf("%d\n",dp[ex[len]-1][0]);
38     }
39 }

 

posted @ 2018-03-15 19:08  JSC!  阅读(187)  评论(0编辑  收藏  举报