[Codefroces401D]Roman and Numbers(状压+数位DP)
题意:给定一个数,求将该数重新排列后mod m==0的方案数
重新排列就考虑到用到哪些数,以及此时mod m的值
于是dp[i][j]表示状态i中mod m==j的方案数
注意:转移的时候只要找到一种可行的转移就行,不然会计算重复的方案数
为了转移的方便,可以将相同的数字放在一起便于检索
Code
#include <cstdio> #include <algorithm> #include <cstring> #define ll long long using namespace std; char s[20]; ll dp[1<<18][110]; int m,l,cnt[20],A[20]; int main(){ scanf("%s%d",s,&m); l=strlen(s); for(int i=0;i<l;++i)cnt[s[i]-'0']++; for(int i=0;i<11;++i)A[i]=A[i-1]+cnt[i-1]; dp[0][0]=1; for(int i=0;i<(1<<l);++i) for(int j=0;j<m;++j) if(dp[i][j]) for(int k=0;k<10;++k){ if((!i)&&(!k))continue; for(int o=A[k];o<A[k+1];++o) if(!(i&(1<<o))){ dp[i|(1<<o)][((j<<3)+(j<<1)+k)%m]+=dp[i][j]; break; } } printf("%lld\n",dp[(1<<l)-1][0]); return 0; }