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.
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.
For each test case, output the answer mod 1000000007(10^9 + 7).
2 1 1 3 1Sample Output
1 4
题意:t 组数据,输入一个 n,k, n个人分配东西,问至少k个人分配到属于自己的编号的方案数。
思路:组合数 + 错排,中间要用到求逆元;n个数字里要求至少k个数字位置不变,其余进行错排的方案数,容易想到不变的数字从k枚举到n,每次取i(k <= i < n)个出来,对剩下的n-i个进行错排;
注意输入 n k,为 long long 时,一定要用 Visual C++
代码:
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define mod 1000000007 #define ll long long #define Max 10010 ll a[Max+10],fic[Max+10]; void fff() { //int i; a[0] = 1; a[1] = 0; a[2] = 1; fic[1] = 1; fic[2] = 2; for(ll i = 3;i<Max;i++) { a[i] = ((i-1)*a[i-1]%mod + (i-1)*a[i-2]%mod)%mod; fic[i] = (fic[i-1] * i)%mod; } } ll p_pow(ll a,ll b) { ll res = 1; while(b) { if(b&1) res = res*a%mod; b>>=1; a = a*a%mod; } return res; } ll C(ll n,ll m) { if(m>n) return 0; if(m==0) return 1; if(m>n-m) m = n-m; ll sum = 1; ll sum1 = 1; ll k = n; for(ll i = 1;i<=m;i++) { sum = sum*k%mod; k--; sum1 = sum1 * i %mod; // 因为 mod 是个素数 所以分母可以先取余,再求逆元; } return sum*p_pow(sum1,mod-2)%mod; } int main() { ll n,m; fff(); int t; scanf("%d",&t); while(t--) { scanf("%lld%lld",&n,&m); ll res = 0; for(ll i = 0;i<m;i++) { res = (res + C(n,i)*a[n-i]%mod) %mod; } printf("%lld\n",(fic[n] - res + mod)%mod ); } return 0; }