1072: [SCOI2007]排列perm

来源:互联网 发布:淘宝装修全屏海报 编辑:程序博客网 时间:2024/04/29 14:32

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


way1:

十位数字,全排列只有10!=3628800,那么如果一个一个枚举,就是10!*15=54432000幸好还撑得住。

所以,用好stl里面的next_permutation就可以了。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int s[11],d,t,num,ans;
int getnum(void);
int main()
{
cin>>t;
for(int i=1;i<=t;i++){
  int sum;
char one;
memset(s,0,sizeof(s));
while(scanf("%c",&one)==1&&one!='\n');
  while(scanf("%c",&one)==1&&one!=' ')
s[++num]=one-'0';
   cin>>d;
  sort(s+1,s+1+num);
  sum=-1;
  do{
   int shuzi=getnum();
    if(shuzi==sum)continue;
    sum=shuzi;
    if(shuzi%d==0)ans++;
   }
   while(next_permutation(s+1,s+1+num));
   cout<<ans<<endl;
   ans=0;
   num=0;
}
return 0;
}
int getnum(void)
{
  int q=0;
  for(int i=1;i<=num;i++){
   q=q*10+s[i];
  }
return q;
}

way2:

状压DP.

数列最多只有十位,把选择数列中的哪些位用01表示为s。


f[s][i]表示当前选择的状态为s,模d余数为i的方案数:


f[s|(1<<k)][(i*10+s[k]-'0')%d]+=f[s][i]


一个数字重复了x次,那么他就被算了x!次,因此最后除以每个数字出现次数的阶乘即可去重。

code:



#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,d,ans,f[1<<10][1<<10],digit[1<<10],tens[10],cnt[10],factorial[11];
char s[20];
int Get_Digit(int x){   
int re=0;   
while(x)    
re+=x&1,x>>=1;   
return re;
}
void State_Compressed_DP(int x){
int i,j;    if(x==1023)     ++x,--x; 
for(i=0;i<n;i++)   
if(1<<i&x) {           
int temp=tens[digit[x]-1]%d*(s[i]-'0')%d;       
for(j=0;j<d;j++)            
f[x][(j+temp)%d]+=f[1<<i^x][j];     
}
}
int main(){
int T,i;  
for(i=0;i<1<<10;i++)   
digit[i]=Get_Digit(i);
tens[0]=1;  
for(i=1;i<10;i++)    
tens[i]=tens[i-1]*10;  
factorial[0]=1; 
for(i=1;i<=10;i++)  
 factorial[i]=factorial[i-1]*i;     
for(cin>>T;T;T--) {
memset(f,0,sizeof f);      
scanf("%s%d",s,&d);   
n=strlen(s);     
f[0][0]=1;    
for(i=1;i<1<<n;i++)     
State_Compressed_DP(i);    
ans=f[(1<<n)-1][0];       
memset(cnt,0,sizeof cnt);     
for(i=0;i<n;i++)     
cnt[s[i]-'0']++;       
for(i=0;i<=9;i++)      
ans/=factorial[cnt[i]];  
cout<<ans<<endl;   
}
return 0;
}  

0 0
原创粉丝点击