洛谷 P4071 [SDOI2016] 排列计数 题解
题目描述
求有多少种 \(1\) 到 \(n\) 的排列 \(a\),满足序列恰好有 \(m\) 个位置 \(i\),使得 \(a_i = i\)。
答案对 \(10^9 + 7\) 取模。
Slove
分为两个部分
首先,从 \(n\) 个数中选取 \(m\) 个, 作为 \(a_i = i\)。
答案为 \(C_n^m\)
其次,对于剩下 \(n - m\) 个,错位排列, 记 \(x\) 个数字的错位排列为 \(D(x)\)
最终答案为 \(C_n^m * D(n - m)\)
由于涉及除法,使用逆元实现组合数
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
//
// By txp2024 www.luogu.com.cn TXP2023 www.github.com
//
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
#pragma once
#include <vector>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <numeric>
#include <ctype.h>
#include <queue>
#include <cstdarg>
#include <climits>
#include <time.h>
#include <iostream>
#include <stdint.h>
#define _FREAD true
#define MAX_INF 1e18
#define MAX_NUM_SIZE 35
#define MAXN (size_t)(1e6)
#define MOD (size_t)(1e9+7)
typedef long long int ll;
typedef unsigned long long int ull;
inline int64_t fpow(int64_t a, int64_t n, int64_t mod) {
int64_t base = a, ret = 1;
while (n) {
if (n & 1) {
ret = ret * base;
ret %= mod;
}
base = base * base;
base %= mod;
n >>= 1;
}
return ret % mod;
}
//快读函数声明
template< typename Type >
inline Type fread(Type* p = nullptr);
//快速输出函数
template<typename Type>
inline void fwrite(Type x);
ll mul[MAXN + 5], inv[MAXN + 5], f[MAXN + 5];
ll t, n, m;
inline void init() {
mul[0] = 1;
for (size_t i = 1; i <= MAXN; i++) {
mul[i] = i * mul[i - 1] % MOD;
}
inv[0] = 1;
inv[MAXN] = fpow(mul[MAXN], MOD - 2, MOD);
for (size_t i = MAXN - 1; i >= 1; --i) {
inv[i] = (i + 1) * inv[i + 1] % MOD;
}
f[0] = 1;
f[1] = 0;
f[2] = 1;
f[3] = 2;
for (size_t i = 4; i <= MAXN; i++) {
f[i] = (i - 1) * (f[i - 1] + f[i - 2]) % MOD;
}
return;
}
int main() {
#ifdef _FREOPEN
freopen("input.txt", "r", stdin);
#endif // _FREOPEN
#ifdef _RUN_TIME
clock_t start = clock();
#endif // _RUN_TIME
fread(&t);
init();
while (t--) {
fread(&n), fread(&m);//scanf("%lld%lld",&n,&m);//cin>>n>>m;
printf("%lld\n", mul[n] * inv[m] % MOD * inv[n - m] % MOD * f[n - m] % MOD);
}
#ifdef _RUN_TIME
printf("The running duration is not less than %ld ms\n", clock() - start);
#endif // _RUN_TIME
return 0;
}
template< typename Type >
inline Type fread(Type* p) {
#if _FREAD
Type ret = 0, sgn = 0, ch = getchar();
while (!isdigit(ch)) {
sgn |= ch == '-', ch = getchar();
}
while (isdigit(ch)) ret = ret * 10 + ch - '0', ch = getchar();
if (p != nullptr) {
*p = Type(sgn ? -ret : ret);
}
return sgn ? -ret : ret;
#else
if (p == nullptr) {
Type temp;
p = &temp;
}
scanf("%lld", p);
return *p;
#endif // _FREAD
}
template<typename Type>
inline void fwrite(Type x) {
int sta[MAX_NUM_SIZE];
int top = 0;
do {
sta[top++] = x % 10, x /= 10;
} while (x);
while (top) {
putchar(sta[--top] + '0');
} // 48 是 '0'
return;
}
/**
* ,----------------, ,---------,
* ,-----------------------, ," ,"|
* ," ,"| ," ," |
* +-----------------------+ | ," ," |
* | .-----------------. | | +---------+ |
* | | | | | | -==----'| |
* | | | | | | | |
* | | C:\>rp++ | | | |`---= | |
* | | | | | |==== ooo | ;
* | | | | | |(((( [33]| ,"
* | `-----------------' | / |(((( | ,"
* +-----------------------+/ | |,"
* /_)______________(_/ +---------+
* _______________________________
* / oooooooooooooooo .o. oooo /, /-----------
* / ==ooooooooooooooo==.o. ooo= // /\--{)B ,"
* /_==__==========__==_ooo__ooo=_/' /___________,"
*
*/

浙公网安备 33010602011771号