LightOJ - 1095 - 番号を配置(错排)

リンク:

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

質問の意味:

第Nの自然数の初期シーケンスとして、このシーケンス{1、2、3 ... N}を考えます。あなたは多くの点で、この順序を並べ替えることができます。Nの合計があるでしょう!アレンジ。あなたは最初のNは自然数、最初のMポジションでの配置数を計算する必要があります。正確にK番号は、その初期位置にあります。

例、N = 5、M = 3、K = 2

現在地第3の位置1における第1の位置と第3位置に3であり、この構成{1、4、3、2、5}を数えるべきです。だから、まさにその最初の3の2が初期位置にあります。

しかし、あなたは{1、2、3、4、5}を数えるべきではありません。

アイデア:

千鳥:
F. [N-] = *(F. + F. [-N-2] [1-N-])、長さのF. [I]スタガ型I(1-N-)。
再帰:
第一工程、残りのn-1の要素の位置kに最初の要素。
第二の工程、すなわちF. [N-2]は、N-2上の残りの第1の位置にkに選択することができる
第一の位置、削除された元の要素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;
}

おすすめ

転載: www.cnblogs.com/YDDDD/p/11886546.html