题意
将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字
解法
状压
f[S][k] 表示选用的位数集合为S,mod m 为k的方案数
注意不能有前导0
但是这样做是有缺陷的
状压本质上是将每个数按下标强行看作不同的数
因此有重复统计的情况
比如n=11,方案只有1种,状压会有2种
根据多重集合的排列,如果一个数字出现了cnt次,那么答案会被重复计算cnt!次,答案需要除以cnt!
上代码
#include<iostream> #include<cstring> #define int long long using namespace std; const int maxs=(1<<18)+10,maxm=110; int w[20],cnt=-1,m,n,f[maxs][maxm]; bool vis[10]; signed main() { for(cin>>n>>m;n;n/=10) w[++cnt]=n%10; f[0][0]=1; for(int s=1;s<1<<cnt+1;s++) { memset(vis,0,sizeof(vis)); for(int i=0;i<=cnt;i++) { if(s==(1<<i)&&!w[i]) break; if(!(s&(1<<i))||vis[w[i]]) continue; vis[w[i]]=1; for(int j=0;j<m;j++) f[s][(j*10+w[i])%m]=f[s][(j*10+w[i])%m]+f[s^(1<<i)][j]; } } cout<<f[(1<<cnt+1)-1][0]<<endl; return 0; }
原文地址:https://www.cnblogs.com/ivanovcraft/p/9021715.html
时间: 2024-10-22 12:54:38