uva11481组合数学错排公式

Consider this sequence {1, 2, 3 ... N}, as an initial sequence of first N natural numbers. You can rearrange this sequence in many ways. There will be a total of N! arrangements. You have to calculate the number of arrangement of first Nnatural numbers, where in first M positions; exactly K numbers are in their initial position.

For Example, N = 5, M = 3, K = 2

You should count this arrangement {1, 4, 3, 2, 5}, here in first 3 positions 1 is in 1st position and 3 in 3rd position. So exactly 2 of its first 3 are in there initial position.

But you should not count {1, 2, 3, 4, 5}.

Input

Input starts with an integer T (≤ 1000), denoting the number of test cases.

Each case contains three integers N (1 ≤ N ≤ 1000), M (M ≤ N), K (0 < K ≤ M).

Output

For each case, print the case number and the total number of possible arrangements modulo 1000000007.

Sample Input

2

5 3 2

10 6 3

Sample Output

Case 1: 12

Case 2: 64320

先从m个数中选出k个,然后枚举后面n-m个数中保持原位置的的数i,n-k-i个数求错排,组合数或错排均要打表

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
#define maxn 1005
const ll mod= 1000000007;
using namespace std;
ll c[maxn][maxn];
ll dp[maxn];
int n,m,k;
int t;
void init()
{
    memset(c,0,sizeof(c));
    for(int i=0;i<maxn;i++)
    for(int j=0;j<=i;j++)
        if(!j||i==j)
        c[i][j]=1;
    else
        c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;

    dp[0]=1;
    dp[1]=0;
    for(ll i=2;i<maxn;i++)
        dp[i]=((dp[i-1]+dp[i-2])%mod*(i-1))%mod;

}
int main()
{
    scanf("%d",&t);
    int w=0;
    init();
    while(t--)
    {w++;
        scanf("%d%d%d",&n,&m,&k);
        ll ans=0;

        for(int i=0;i<=n-m;i++)
            ans=(ans+c[n-m][i]*dp[n-k-i])%mod;
        printf("Case %d: %lld\n",w,c[m][k]*ans%mod);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sdauguanweihong/article/details/88757945
今日推荐