CF401D 【Roman and Numbers】
阿新 • • 發佈:2018-05-10
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】