Given a string s and a positive integer d you have to determine how many permutations of s are divisible by d.
Input
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case contains a string s (1 ≤ slength ≤ 10) and an integer d (1 ≤ d ≤ 1001). s will only contain decimal digits.
Output
For each case, print the case number and the number of permutations of s that are divisible by d.
Sample Input | Output for Sample Input |
3 000 1 1234567890 1 123434 2 | Case 1: 1 Case 2: 3628800 Case 3: 90 |
给你一个字符串,问你用这些数字能排列出多少种不同的数字能被d整除。
直接状压求出所有能被d整除的排列,然后再除以每个数字出现次数的阶乘,就是答案了。
DP的时候优化一点,就不会超时了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 1e9
#define endl '\n'
#define mod 100000007
#define LL long long
using namespace std;
int dp[1100][1100];
int main(void)
{
int T,n,d,i,j,k;
scanf("%d",&T);
char s[15];
int f[15],a[15],num[15];
int cas = 1;
f[0] = 1;
for(i=1;i<=10;i++)
f[i] = f[i-1]*i;
while(T--)
{
scanf("%s%d",s,&d);
n = strlen(s);
memset(num,0,sizeof(num));
memset(dp,0,sizeof(dp));
for(i=0;i<n;i++)
{
a[i] = s[i] - '0';
num[a[i]]++;
}
dp[0][0] = 1;
for(i=0;i<(1<<n);i++)
{
for(j=0;j<n;j++)
{
if(i&(1<<j))
continue;
for(k=0;k<d;k++)
{
if(dp[i][k]==0)
continue;
dp[i|(1<<j)][(k*10+a[j])%d]+=dp[i][k];
}
}
}
int ans = dp[(1<<n)-1][0];
for(i=0;i<10;i++)
ans /= f[num[i]];
printf("Case %d: %d\n",cas++,ans);
}
return 0;
}