1. 程式人生 > >牛客網國慶集訓派對Day3 H-Travel(計數問題)

牛客網國慶集訓派對Day3 H-Travel(計數問題)

思路來源

題解

因為這m次旅遊互不相干,所以在這n-1條邊裡選m-1條邊將其割斷,將原樹劃分為m塊即可。

總方案數考慮順序,取這m塊的全排列即可。

由於原圖是一棵樹,顯然與怎麼連無關,所以輸入部分多餘。

心得

學了盧卡斯定理之後,總想用盧卡斯,實際上用不到。

這裡C(n,m)用原公式處理一下(n!)*(m!)*((n-m)!))的逆元即可,

n,m1e5;初始化處理階乘,費馬小定理解決逆元。

程式碼

#include <iostream>
#include <algorithm> 
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const double INF=0x3f3f3f3f;
const int maxn=1e5+10; 
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int> 
#define si set<int>
#define pii pair<double,int> 
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a)) 
using namespace std;
ll jc[maxn];
void init()//預處理階乘 
{
	jc[0]=1,jc[1]=1;
	rep(i,2,maxn)
	{
		jc[i]=jc[i-1]*i;
		if(jc[i]>=mod)jc[i]%=mod;
	} 
}
ll modpow(ll x,ll n)
{
	ll res=1;
	while(n)
	{
		if(n&1)res*=x;
		if(res>=mod)res%=mod;
		x*=x;
		if(x>=mod)x%=mod;
		n>>=1;
	}
	return res;
}
ll c(ll n,ll m)
{
	return jc[n]*modpow(jc[m]*jc[n-m]%mod,mod-2)%mod; 
}
int main()
{ 
    ll t,n,m;
    init();
    scll(t);
    while(t--)
    {
    	scll(n),scll(m);
    	int a,b;
    	rep(i,0,n-2)sci(a),sci(b);
    	printf("%lld\n",c(n-1,m-1)*jc[m]%mod);
    }
	return 0;
}