Codeforces 991E. Bus Number (DFS+排列組合)

解題思路

  1. 將每一個數字出現的次數存在一個數組num[]中(與順序無關)。
  2. 將出現過的數字i從1到num[i]遍歷。(i from 0 to 9)
  3. 獲得要使用的數字次數數組a[]。
  4. 對於每一種a使用排列組合公式:
    ios

  5. ans += 上面那個公式。(每用一次這個公式對應一個a)c++

排列組合公式註解

  1. 減號左邊表示的是sum個數字全排列並去重。
  2. 減號右邊表示的是從a[0]中選出一個0當作第一個數字,並對其餘數字全排列並去重。

抱歉,寫的可能比較混亂,還有部分細節須要讀者處理。數組

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

string s;
int num[10];
ll jc[20];//階乘 
int tempNum[10];
ll ans = 0;

void dfs(int x){
    //若是0~9都填充好了數字 
    if(x == 10){
        //cnt表示全部數字的個數 
        int cnt = 0;
        for(int i = 0;i < 10; ++i){
            cnt += tempNum[i];
        }
        //排列組合公式 開始 
        ll p = jc[cnt];
        for(int i = 0;i < 10; ++i){
            p /= jc[tempNum[i]];
        }
        if(tempNum[0] >= 1)
            p -= (p*tempNum[0]/cnt);
        //排列組合公式 結束 
        ans += p;
        return ;
    }
    //對於出現過的數字,個數從1開始 
    for(int i = 1;i <= num[x]; ++i){
        tempNum[x] = i;
        dfs(x+1);
    }
    if(num[x] == 0){
        dfs(x+1);
    }
}


int main(){
    ios::sync_with_stdio(false);
    cin >> s;
    for(auto i:s) num[i-'0']++;
    //算階乘 
    jc[0] = 1;
    for(ll i = 1;i <= 19; ++i){
        jc[i] = jc[i-1]*i;
    }
    dfs(0);
    cout << ans << endl;
    return 0;   
}
相關文章
相關標籤/搜索