Description

给定正整数 n,m,问有多少个正整数满足: (1)不含前导 0; (2)是 m 的倍数; (3)可以通过重排列各个数位得到 n。

Input

一行两个整数 n,m。

Output

一行一个整数表示答案对 998244353 取模的结果。

Sample Input

1 1

Sample Output

1

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]);
}