牛客國慶集訓派對Day3___H Travel——連通+組合數
阿新 • • 發佈:2018-12-13
題目大意:
題目較短,但第一次理解起來可能有點繞腦。最後要求的是不同的旅遊方案數,也就是不同路線選取的方案數。
解題思路:
一開始以為是圖論,想了一下好像無從下口,看了一下題解原來是有規律可循,當時答案為,當時就可以用條邊將整個圖(連通的)分成個區域,恰好對應題目中的次旅遊,也就是說每次旅遊選取這個區域裡的一個,那麼很顯然結果我們就要乘以這個的全排列,即旅遊的順序不同。 然後考慮的是怎麼選取這條邊,就是從條邊中任意選取,也就是,求個組合數。 最後答案即為
程式碼思路:
看到資料範圍, 為 ,用逆元求組合數即可。
核心:對題目的理解,算得上是一道讀題題吧,前提是會一點數論的知識。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1 << 20; const int mod = 1000000007; int t, n, m, ta, tb; ll c[maxn]; ll PowerMod(ll a, ll b, ll c) { //快速冪 ll ans = 1; a = a % c; while (b>0) { if (b % 2 == 1) ans = (ans * a) % c; b = b / 2; a = (a * a) % c; } return ans; } void init() { //先打出階乘,節省時間 c[1] = 1; for (int i = 2; i <= maxn; i++) { c[i] = c[i - 1] * i%mod; } } ll C(ll n, ll m) { //逆元求組合數 return c[n] * PowerMod(c[m] * c[n - m] % mod, mod - 2, mod) % mod; } int main(void) { scanf("%d", &t); init(); while (t-- >0 ) { scanf("%d%d", &n, &m); for (int i = 0; i < n - 1; i++) scanf("%d%d",&ta,&tb); if (m == 1) { printf("1\n"); continue; } ll ans = C(n - 1, m - 1); ans = (ans*c[m]) % mod; printf("%lld\n", ans); } return 0; }