题解:SP19147 INS14F - Save CodeVillage
题解:SP19147 INS14F - Save CodeVillage
Tag
组合数,逆元,抽屉原理。
Solution
分类讨论一下。
- 当 \(k>\dfrac{n}{2}\) 时,根据抽屉原理,我们发现,无论我们怎么选取数列,任意两个数列间一定是有重复的元素的,所以我们随便取都合法,方案数为:
\[\binom{n}{k}\times k!
\]
- 当 \(k\le \dfrac{n}{2}\) 时,任意选取已经不能保证,那我们就钦定一个数为两个数列的重复元素,剩下 \(k-1\) 个数任意取就行了。方案数为:
\[\binom{n-1}{k-1}\times k!
\]
这两个式子是很好求的,我们可以 \(\mathcal O(n)\) 预处理出阶乘即阶乘的逆元,直接套公式输出即可。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
const int p=1e9+7;
int inv[N],fac[N],nv[N];
int T;
void init()
{
fac[0]=inv[1]=nv[0]=1;
for(int i=1;i<=N-5;i++)
fac[i]=fac[i-1]*i%p;
for(int i=2;i<=N-5;i++)
inv[i]=(p-p/i)*inv[p%i]%p;
for(int i=1;i<=N-5;i++)
nv[i]=nv[i-1]*inv[i]%p;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
init();
cin>>T;
while(T--)
{
int n,k;
cin>>n>>k;
if(n<k*2)
cout<<fac[n]*nv[k]%p*nv[n-k]%p*fac[k]%p<<endl;
else
cout<<fac[n-1]*nv[k-1]%p*nv[n-k]%p*fac[k]%p<<endl;
}
return 0;
}

浙公网安备 33010602011771号