Link:
BZOJ 1072 传送门
Solution:
一道直接next_permutation纯暴力就能过的题?
难道2007年时大家都不知道next_permutation这个函数吗
还是用复杂度更优的状压DP吧
设$dp[i][j]$为状态为$i$且对$d$余$j$的个数,
注意$dp[(1<<len)-1][0]$最后除去$\prod_{i=0}^9 cnt[i]!$,排除重复项
现在对状压DP状态的选取有了些感悟,
一般来说第一项表示状态,而第二项表示的一般都是于答案相关且包含答案情况的
(EX:求整除,表示当前对$d$的余数)
Code:
#include <bits/stdc++.h>using namespace std;int T,d,len,cnt[15],dupli[15],dp[1200][1010]; char s[15];int main() {scanf("%d",&T);while(T--){scanf("%s %d",s,&d);len=strlen(s);for(int i=0;i<15;i++) dupli[i]=1;memset(cnt,0,sizeof(cnt));memset(dp,0,sizeof(dp));for(int i=0;i<len;i++)cnt[s[i]-'0']++,dupli[s[i]-'0']*=cnt[s[i]-'0'];dp[0][0]=1;for(int i=0;i<(1<<len);i++)for(int j=0;j<d;j++)if(dp[i][j])for(int k=0;k<len;k++)if(!(i&(1<<k)))dp[i|(1<<k)][(j*10+(s[k]-'0'))%d]+=dp[i][j];for(int i=0;i<=9;i++) dp[(1<<len)-1][0]/=dupli[i];printf("%d\n",dp[(1<<len)-1][0]);}return 0; }