K - Wand(组合数+错排公式)

N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, numbered from 1 to n(Wand_i owned by wizard_i). After the meeting, n wizards will take a wand one by one in the order of 1 to n. A boring wizard decided to reorder the wands. He is wondering how many ways to reorder the wands so that at least k wizards can get his own wand.

For example, n=3. Initially, the wands are w1 w2 w3. After reordering, the wands become w2 w1 w3. So, wizard 1 will take w2, wizard 2 will take w1, wizard 3 will take w3, only wizard 3 get his own wand.

Input

First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

For each test case: Two number n and k.

1<=n <=10000.1<=k<=100. k<=n.

Output

For each test case, output the answer mod 1000000007(10^9 + 7).

Sample Input

2
1 1
3 1

Sample Output

1
4
题解:n个人排位,求至少k个人能做到自己位置的方法树。那么我们就要求出组合数Cnm,错排递推数组dp[i],
然后还有数据的问题,要反向考虑,从k到n转换为从0到k(左闭右开),那么还要计算出排列递推数组fac[i](即阶乘)位总方案数,一减即得答案。
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=10010;
const int mod=1e9+7;
ll C[maxn][105],dp[maxn],fac[maxn];
void Init()
{
    fac[0]=1,fac[1]=1;
    for(int i=2;i<=10000;i++)//计算总方案数,即阶乘数
        fac[i]=i*fac[i-1]%mod;
    dp[0]=1,dp[1]=0,dp[2]=1;
    for(int i=3;i<=10000;i++)//错排公式
    {
        dp[i]=((i-1)*(dp[i-1]+dp[i-2])%mod)%mod;;
    }
    C[1][0]=1;
    C[1][1]=1;
    for(int i=2;i<=10000;i++)//组合公式
    {
        C[i][0]=1;
        for(int j=1;j<=i&&j<=100;j++)
        {
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(0);
    Init();
    int t,n,k;
    cin>>t;
    while(t--)
    {
        cin>>n>>k;
        ll ans=0;
        for(int i=0;i<k;i++)//由于正向考虑会T,并且k<100,那么我们反向考虑情况,用总情况减去即可
        {                   //反向情况即为:从n个数中选取i个,剩下n-i个错排,i范围从0到k
            ans=(ans+(C[n][i]*dp[n-i])%mod)%mod;
        }
        cout<<(fac[n]-ans+mod)%mod<<endl;//注意输出也要取模
    }
    return 0;
}

 

上一篇:F-有趣的数字(逆元+快速幂)


下一篇:一道Lucas定理的板子题