bzoj 1072 排列
阿新 • • 發佈:2018-12-04
ive () spa des ++i etc 是個 mes char s
Written with StackEdit.
Description
給一個數字串\(s\)和正整數\(d\), 統計s有多少種不同的排列能被\(d\)整除(可以有前導\(0\))。
例如\(123434\)有\(90\)種排列能被\(2\)整除,其中末位為\(2\)的有\(30\)種,末位為\(4\)的有\(60\)種。
Input
輸入第一行是一個整數\(T\),表示測試數據的個數,以下每行一組\(s\)和\(d\),中間用空格隔開。\(s\)保證只包含數字\(0, 1 , 2, 3, 4, 5, 6, 7, 8, 9.\)
Output
每個數據僅一行,表示能被\(d\)整除的排列的個數。
Sample Input
7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29
Sample Output
1
3
3628800
90
3
6
1398
HINT
在前三個例子中,排列分別有\(1, 3, 3628800\)種,它們都是\(1\)的倍數。
\(s\)的長度不超過\(10, 1<=d<=1000, 1<=T<=15.\)
Solution
開始覺得就是個弱智\(dfs\),寫了一發,結果\(T\)了.
嚇得我去寫狀壓\(dp\),然後想的時候發現\(dfs\)是可以做的.只是我第一次的枚舉姿勢不對...
- \(dfs\)過程中傳遞余數\(r\)
- 開始的時候我是枚舉的填入串中的第幾個數字,算階乘去重把我卡\(T\)了.
#include<bits/stdc++.h> using namespace std; typedef long long LoveLive; inline int read() { int out=0,fh=1; char jp=getchar(); while ((jp>‘9‘||jp<‘0‘)&&jp!=‘-‘) jp=getchar(); if (jp==‘-‘) { fh=-1; jp=getchar(); } while (jp>=‘0‘&&jp<=‘9‘) { out=out*10+jp-‘0‘; jp=getchar(); } return out*fh; } const int MAXN=11; int vis[MAXN]; int ans=0; char s[MAXN]; int d,n; int t[MAXN]; void dfs(int k,int r) { if(k>n) { ans+=(r==0); return; } for(register int i=0;i<=9;++i) { if(t[i]) { --t[i]; dfs(k+1,(r*10+i)%d); ++t[i]; } } } int main() { int T=read(); while(T--) { scanf("%s",s+1); n=strlen(s+1); d=read(); memset(t,0,sizeof t); for(register int i=1;i<=n;++i) ++t[s[i]-‘0‘]; ans=0; dfs(1,0); printf("%d\n",ans); } return 0; }
bzoj 1072 排列