bzoj1072: [SCOI2007]排列perm
1072: [SCOI2007]排列perm
Time Limit: 10 Sec Memory Limit: 128 MBDescription
给一个数字串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
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29
Sample Output
1
3
3628800
90
3
6
1398
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 }