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 31∼3 | 10^3103 | 88 | 10 \sim 1210∼12 | 10^3103 | 10^3103 |
4 \sim 64∼6 | 10^3103 | 1212 | 13 \sim 1413∼14 | 5 \times 10^55×105 | 10^3103 |
7 \sim 97∼9 | 10^3103 | 100100 | 15 \sim 2015∼20 | 5 \times 10^55×105 | 10^6106 |
对于全部的测试点,保证 1 \leq T \leq 5 \times 10^51≤T≤5×105,1 \leq n \leq 10^61≤n≤106,0 \leq m \leq 10^60≤m≤106。
#include <bits/stdc++.h>
using namespace std;
const int mode=1e9+7;
const int N=1e6+10;
int f[N];
int fact[N];
typedef long long LL;
int qmi(int a,int k,int p)
{
LL res=1;
while(k)
{
if(k&1)
{
res=res*a%mode;
}
a=(LL)a*a%mode;
k>>=1;
}
return res;
}
int C(int a,int b)
{
return (LL)fact[a]*qmi(fact[b],mode-2,mode)%mode*qmi(fact[a-b],mode-2,mode)%mode;
}
void init()
{
fact[0]=1;
for(int i=1;i<N;i++)
{
fact[i]=(LL)fact[i-1]*i%mode;
}
}
int main()
{
f[0]=1;
f[1]=0;
f[2]=1;
for(int i=3;i<N;i++)
{
f[i]=(LL)(i-1)*(f[i-1]+f[i-2])%mode;
}
init();
int T;
cin>>T;
while(T--)
{
int n,m;
cin>>n>>m;
cout<<(LL)C(n,m)*f[n-m]%mode<<endl;
}
return 0;
}