列表

详情


NC20584. [SDOI2016]排列计数

描述

求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的。
序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模。

输入描述

第一行一个数 T,表示有 T 组数据。
接下来 T 行,每行两个整数 n、m。
T=500000,n ≤ 1000000,m ≤ 1000000

输出描述

输出 T 行,每行一个数,表示求出的序列数

示例1

输入:

5
1 0
1 1
5 2
100 50
10000 5000

输出:

0
1
20
578028887
60695423

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 367ms, 内存消耗: 36480K, 提交时间: 2020-10-09 21:44:37

#include<iostream>
#include<cstdio>
using namespace std;
const int M=1000000;
const int MOD=1e9+7;
long long t,n,m,d[M+1],jc[M+1],inv[M+1],invjc[M+1];
void pre(){
	d[0]=invjc[0]=invjc[1]=inv[1]=d[2]=jc[0]=jc[1]=1;
	for(register int i=2;i<=M;i++){
		inv[i]=((MOD-MOD/i)*inv[MOD%i])%MOD;
		jc[i]=(i*jc[i-1])%MOD;
		invjc[i]=(invjc[i-1]*inv[i])%MOD;
	}
	for(register int i=3;i<=M;i++){
		d[i]=(i-1)*(d[i-1]+d[i-2])%MOD;
	}
}
int main()
{
	pre();
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld",&n,&m);
		printf("%lld\n",(((jc[n]*invjc[m]%MOD)*invjc[n-m]%MOD)*d[n-m]%MOD));
	}
	return 0;
}

上一题