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
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29
Sample Output
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;
}