题解: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;
}
posted @ 2025-02-14 16:43  Ryan_Adam  阅读(17)  评论(0)    收藏  举报