码迷,mamicode.com
首页 > 其他好文 > 详细

LightOJ - 1095 - Arrange the Numbers(错排)

时间:2019-11-19 01:11:48      阅读:62      评论:0      收藏:0      [点我收藏+]

标签:pac   cst   amp   while   https   位置   type   cas   range   

链接:

https://vjudge.net/problem/LightOJ-1095

题意:

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 N natural 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}.

思路:

错排:
F[n] = (n-1)*(F[n-1]+F[n-2]),F[i]为长度i的错排种类。
递推:
第一步,首元素插到剩下n-1个元素位置k。
第二步,可以选择将k插到首位置,此时就剩下n-2个,即F[n-2]
可以不插到首位置,将原本k位置元素删除,k插到首元素位置,看成k位置,则为F[n-1]

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<utility>

using namespace std;
typedef long long LL;
const int INF = 1e9;

const int MAXN = 1e3+10;
const int MOD = 1e9+7;

int n, k, m;
LL P[MAXN], F[MAXN];

LL PowMod(LL a, LL b)
{
    LL res = 1;
    while(b)
    {
        if (b&1)
            res = (1LL*res*a)%MOD;
        a = (1LL*a*a)%MOD;
        b >>= 1;
    }
    return res;
}

LL Com(LL a, LL b)
{
    if (b == 0 || a == b)
        return 1;
    return 1LL*P[a]*PowMod(P[b]*P[a-b]%MOD, MOD-2)%MOD;
}

void Init()
{
    P[1] = 1;
    for (int i = 2;i < MAXN;i++)
        P[i] = 1LL*i*P[i-1]%MOD;
    F[1] = 0, F[0] = F[2] = 1;
    for (int i = 3;i < MAXN;i++)
        F[i] = 1LL*(i-1)*((F[i-1]+F[i-2])%MOD)%MOD;
}

int main()
{
    Init();
    int cnt = 0;
    int t;
    scanf("%d", &t);
    while(t--)
    {
        printf("Case %d:", ++cnt);
        scanf("%d%d%d", &n, &m, &k);
        LL res = 0LL;
        for (int i = 0;i <= n-m;i++)
            res = ((res + 1LL*Com(n-m, i)*F[n-k-i]%MOD)%MOD+MOD)%MOD;
        res = 1LL*res*Com(m, k)%MOD;
        printf(" %lld\n", res);
    }
    
    return 0;
}

LightOJ - 1095 - Arrange the Numbers(错排)

标签:pac   cst   amp   while   https   位置   type   cas   range   

原文地址:https://www.cnblogs.com/YDDDD/p/11886546.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!