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; }
?