给定正整数 n,m,问有多少个正整数满足: (1)不含前导 0; (2)是 m 的倍数; (3)可以通过重排列各个数位得到 n。
Input一行两个整数 n,m。
Output一行一个整数表示答案对 998244353 取模的结果。
Sample Input1 1
Sample Output1
Data Constraint对于 20%的数据,n<10^10。
对于 50%的数据,n<10^16,m<=20。
对于 100%的数据,n<10^20,m<=100。
数位DP
状压记录0到9剩余个数以及 mod m 的值的情况下的方案数
但是这个暴力记录会TLE,所以要用一些小技巧
考虑一下可以避免无用状态,考虑用i*个数来表示状态
这样的话,如果要找 j 的数量,可以用状态i/c[j]%a[j]就可以得知
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=998244353;
long long c[12],s[12],f[65535][117],w[12];
int a[12],m;
char st[30];
void work(int x)
{
for(int i=9; i>=0; i--) w[i]=a[i]-(x/c[i]),x%=c[i];
}
int main()
{
freopen("number.in","r",stdin); freopen("number.out","w",stdout);
scanf("%s%d",st,&m);
int l=strlen(st);
for(int i=0; i<l; i++) a[st[i]-48]++;
c[0]=1; s[0]=c[0]*a[0];
for (int i=1; i<=9; i++) c[i]=s[i-1]+1,s[i]=s[i-1]+c[i]*a[i];
for (int i=1; i<=9; i++) if (a[i]>0) f[c[i]][i%m]=1;
for (int i=1; i<=s[9]; i++)
{
work(i);
for(int j=0; j<=9; j++) if(w[j]>0)
for(int k=0;k<=m-1;k++) (f[i+c[j]][(k*10+j)%m]+=f[i][k]+mod)%=mod;
}
printf("%d",f[s[9]][0]);
}