Roman is a young mathematician, very famous in Uzhland. Unfortunately, Sereja doesn't think so. To make Sereja change his mind, Roman is ready to solve any mathematical problem. After some thought, Sereja asked Roma to find, how many numbers are close to number n, modulo m.
Number x is considered close to number n modulo m, if:
- it can be obtained by rearranging the digits of number n,
- it doesn't have any leading zeroes,
- the remainder after dividing number x by m equals 0.
Roman is a good mathematician, but the number of such numbers is too huge for him. So he asks you to help him.
The first line contains two integers: n (1 ≤ n < 1018) and m (1 ≤ m ≤ 100).
In a single line print a single integer — the number of numbers close to number n modulo m.
104 2
3
223 4
1
7067678 8
47
In the first sample the required numbers are: 104, 140, 410.
In the second sample the required number is 232.
解题报告: 昨晚CF的题。昨晚三十几分钟搞定了前3题,简单看了一下,感觉没什么思路,就直接睡觉去了。早上看到队友说他写状态压缩,赛后过了。想了一下,的确可以过:dp[i][j],i的二进制表示数字有没有被使用,j表示余数,dp[i][j]表示使用i代表的那些数字后余数为j的数量。然后,状态压缩计算即可。代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
LL dp[500000][100];
char str[20];
int num[10];
int main()
{
int n,m;
scanf("%s%d",str,&m);
int len = strlen(str);
for(int i=0;i<len;i++) if(str[i]!='0')
dp[1<<i][(str[i]-'0')%m]++;
for(int i=2;i<(1<<len);i++)
{
for(int j=0;j<len;j++) if(i&(1<<j))
{
int old = i^(1<<j);
for(int k=0;k<m;k++) if(dp[old][k])
{
dp[i][(k*10+str[j]-'0')%m]+=dp[old][k];
}
}
}
LL ans = dp[(1<<len)-1][0];
for(int i=0;i<len;i++)
num[str[i]-'0']++;
for(int i=0;i<10;i++)
for(int j=2;j<=num[i];j++)
ans/=j;
printf("%I64d\n", ans);
}