-
codeforces 401D
-
题意
-
将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字
-
f[S][k] 表示选用的位数集合为S,mod m 为k的方案数
-
注意不能有前导0
-
但是这样做是有缺陷的
-
状压本质上是将每个数按下标强行看作不同的数
-
因此有重复统计的情况
-
比如n=11,方案只有1种,状压会有2种
-
根据多重集合的排列,如果一个数字出现了cnt次,那么答案会被重复计算cnt!次,答案需要除以cnt!
-
#include<bits/stdc++.h> #define maxn 1<<18 #define ll long long using namespace std; ll n,m,dp[maxn+1][123],temp; ll fac[25],num[15],x,y,z; string str; int main() { ios::sync_with_stdio(false); cin>>str>>m; n=str.size(); dp[0][0]=fac[0]=1; for(int i=0; i<n; i++) { num[str[i]-'0']++; fac[i+1]=fac[i]*(i+1); } ll tot=1<<n; for(int i=0; i<tot; i++) for(int k=0; k<m; k++) { if(!dp[i][k])continue; for(int j=0; j<n; j++) { x=str[j]-'0'; if(i==0&&x==0)continue; if((1<<j)&i)continue; y=((1<<j)|i); z=(k*10+x)%m; dp[y][z]+=dp[i][k]; } } temp=1; for(int i=0; i<10; i++) temp*=fac[num[i]]; dp[tot-1][0]/=temp; printf("%lld\n",dp[tot-1][0]); return 0; }
codeforces 401D-状压DP
最新推荐文章于 2022-08-16 21:52:06 发布