欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【NOIP提高A组模拟2018.8.18】 number

程序员文章站 2024-03-20 11:07:52
...

【题目描述】

给定正整数 n,m,问有多少个正整数满足:

 (1)不含前导 0;

 (2)是 m 的倍数;

 (3)可以通过重排列各个数位得到 n。

【输入格式】

一行两个整数 n,m。

【输出格式】

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

【样例输入】

1 1

【样例输出】

1

【数据规模】

对于 20%的数据,n<10^10。

对于 50%的数据,n<10^16,m<=20。

对于 100%的数据,n<10^20,m<=100。

 

分析:

数位DP。

状压记录 0 到 9 剩余个数以及 mod m 的值的情况下的方 案数。转移时枚举最高位填的数字,最后一次转移不要枚 举 0。

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
long long c[12],b[12],dp[65535][117],w[12];
int a[12],m;
string s;
int main(){
    cin>>s>>m;
    int len=s.size();
    for(int i=0; i<len; i++) a[s[i]-'0']++;
    c[0]=1;
	b[0]=c[0]*a[0];
    for (int i=1; i<=9; i++){
		c[i]=b[i-1]+1;b[i]=b[i-1]+c[i]*a[i];
    } 
    for(int i=1; i<=9; i++)
		if (a[i]>0) dp[c[i]][i%m]=1;
    for (int i=1; i<=b[9]; i++){
		int x=i;
        for(int j=9; j>=0; j--) w[j]=a[j]-(x/c[j]),x%=c[j];
        for(int j=0; j<=9; j++) 
			if(w[j]>0)for(int k=0;k<=m-1;k++){
				dp[i+c[j]][(k*10+j)%m]+=dp[i][k]+mod;
				dp[i+c[j]][(k*10+j)%m]%=mod;
			} 
    }
    cout<<dp[b[9]][0]<<endl;
}