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;
}