[排列组合 错排 逆元] P4071 [SDOI2016]排列计数
Posted 鱼竿钓鱼干
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[排列组合 错排 逆元] P4071 [SDOI2016]排列计数相关的知识,希望对你有一定的参考价值。
[排列组合 错排] P4071 [SDOI2016]排列计数
题目
思路
已知错排公式
D
(
n
)
=
(
n
−
1
)
(
D
(
n
−
1
)
+
D
(
n
−
2
)
)
D(n)=(n-1)(D(n-1)+D(n-2))
D(n)=(n−1)(D(n−1)+D(n−2))
该题要求恰好有m个位置满足ai=i,也就是说n-m个位置是错排的
那么答案就是
a
n
s
=
C
n
m
∗
D
(
n
−
m
)
ans=C_n^m*D(n-m)
ans=Cnm∗D(n−m)
代码
// Problem: P4071 [SDOI2016]排列计数
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4071
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// FishingRod
#include<bits/stdc++.h>
using namespace std;
#define endl "\\n"
typedef long long LL;
typedef pair<int,int> PII;
//#define MULINPUT
/*DATA & KEY
*/
int T;
const int mod=1e9+7,N=1e6+10;
LL fact[N],infact[N],D[N]={1,0};
LL fp(LL a,LL b){
LL res=1;
while(b){
if(b&1)res=res*a%mod;
b>>=1;
a=a*a%mod;
}
return res%mod;
}
// 预处理阶乘的余数和阶乘逆元的余数
void solve(int C)
{
//NEW DATA CLEAN
//NOTE!!!
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i ++ )
{
fact[i] = (LL)fact[i - 1] * i % mod;
infact[i] = (LL)infact[i - 1] * fp(i, mod - 2) % mod;
}
for(int i=2;i<=N;i++)D[i]=(i-1)*(D[i-1]+D[i-2])%mod;
cin>>T;
while(T--){
int n,m;cin>>n>>m;
LL ans=fact[n]*infact[m]%mod*infact[n-m]%mod*D[n-m]%mod;
cout<<ans<<endl;
}
}
int main()
{
#ifdef MULINPUT
scanf("%d",&T);
for(int i=1;i<=T;i++)solve(i);
#else
solve(1);
#endif
return 0;
}
以上是关于[排列组合 错排 逆元] P4071 [SDOI2016]排列计数的主要内容,如果未能解决你的问题,请参考以下文章