题目:
分析:
我们以
m
m
m的两种情况进行分析:
当
m
=
1
m=1
m=1时:果断输出
1
1
1
当
m
>
1
m>1
m>1时:我们可以用
m
−
1
m-1
m−1条边,将这
n
n
n个点组成的图划分为
m
m
m个部分,那么这样的话我们就考虑将这
m
m
m个部分进行排列,也就是
m
m
m的全排列
→
m
!
→m!
→m!
而我们一共有
n
−
1
n-1
n−1条边,要选出
m
−
1
m-1
m−1条,即求组合:
C
m
−
1
n
−
1
C_{m-1}^{n-1}
Cm−1n−1
当然这样还是只能得到部分分,因为
C
m
−
1
n
−
1
C_{m-1}^{n-1}
Cm−1n−1实在太大了,需要边运算边模,但除法并不具有这样的性质,故我们要将其转化为乘法,我们知道除以一个数,等于乘以这个数的乘法逆元,而再根据费马小定理可以知道一个数
(
x
)
(x)
(x)的乘法逆元
(
y
)
(y)
(y)
=
x
模
数
−
2
=x^{模数-2}
=x模数−2
而对于上述式子,可以通过快速幂迅速求解
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
const int h=1 << 20;
#define ch cheap
#define XJQ (int)1000000007
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
LL n,m;
LL f[(int)1e5+5];
void fac()
{
f[1]=1;
for(int i=2;i<=n;i++) f[i]=(LL)f[i-1]*i%XJQ;
return;
}
LL gd(LL x,LL y)
{
LL ans=1;
while(y)
{
if(y&1) ans=ans*x%XJQ;
y/=2;
x=x*x%XJQ;
}
return ans;
}
LL c()
{
return f[n-1]*gd(f[m-1]*f[n-m]%XJQ,XJQ-2)%XJQ;
}
int main()
{
LL t=read();
LL x;
while(t--)
{
n=read(),m=read();
fac();
for(int i=0;i<2*n-2;i++) x=read();
if(m==1) {printf("1\n");continue;}
printf("%lld\n",(c())*f[m]%XJQ);
}
return 0;
}