1. 程式人生 > >CF401D 【Roman and Numbers】

CF401D 【Roman and Numbers】

ans size ret iostream man esp AS return pan

題意
將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; }

CF401D 【Roman and Numbers】