P4071 [SDOI2016]排列计数

题目描述

求有多少种 11 到 nn 的排列 aa,满足序列恰好有 mm 个位置 ii,使得 a_i = iai=i。

答案对 10^9 + 7109+7 取模。

输入格式

本题单测试点内有多组数据。

输入的第一行是一个整数 TT,代表测试数据的整数。

以下 TT 行,每行描述一组测试数据。

对于每组测试数据,每行输入两个整数,依次代表 nn 和 mm。

输出格式

共输出 TT 行,对于每组测试数据,输出一行一个整数代表答案。

输入输出样例

输入 #1
5
1 0
1 1
5 2
100 50
10000 5000
输出 #1
0
1
20
578028887
60695423

说明/提示

数据规模与约定

本题共 20 个测试点,各测试点等分,其数据规模如下表。

测试点编号T =T=n, m \leqn,m测试点编号T =T=n, m \leqn,m
1\sim 313 10^3103 88 10 \sim 121012 10^3103 10^3103
4 \sim 646 10^3103 1212 13 \sim 141314 5 \times 10^55×105 10^3103
7 \sim 979 10^3103 100100 15 \sim 201520 5 \times 10^55×105 10^6106

对于全部的测试点,保证 1 \leq T \leq 5 \times 10^51T5×105,1 \leq n \leq 10^61n106,0 \leq m \leq 10^60m106。

// 错排模板题,f[i]为错排
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 7;
typedef long long LL;
const LL MOD = 1e9 + 7;
LL f[MAXN], fac[MAXN];
void init() {
    f[1] = 0; f[2] = 1;
    for (int i = 3; i < MAXN; i++) f[i] = (i - 1) * (f[i - 1] + f[i - 2]) % MOD;
    fac[0] = 1;
    for (int i = 1; i < MAXN; i++) fac[i] = (fac[i - 1] * i) % MOD;
}
LL ksm(LL a, LL b) {
    LL ans = 1;
    while (b) {
        if (b & 1) ans = ans * a % MOD;
        a = a * a % MOD;
        b >>= 1;
    }
    return ans;
}
LL inv(LL a) {
    return ksm(a, MOD - 2);
}
int main() {
    init();
    int T, n, m;
    cin >> T;
    init();
    while (T--) {
        scanf("%d%d", &n, &m);
        if (n == m) {
            printf("1\n");
            continue;
        }
        LL ans = fac[n] * inv(fac[m]) % MOD * inv(fac[n - m]) % MOD * f[n - m] % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}
posted @ 2020-07-23 16:53  HighLights  阅读(160)  评论(0)    收藏  举报