错排问题
考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。 n个元素的错排数记为Dn。
递推公式:Dn=(n-1)(Dn-1+Dn-2) n>3, D1 = 0 , D2 = 1;
求大组合数取余(快速幂+逆元费马小定理)
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000005
const int mod = 1e9+7;
typedef long long ll;
ll f[maxn],fi[maxn];
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans%mod;
}
void F(){
f[0]=1;
for(int i=1;i<=maxn;i++){
f[i]=f[i-1]*i%mod;
}
}
ll C(ll x,ll y){
ll ans=f[x]%mod*qpow(f[y]*f[x-y]%mod,mod-2)%mod;
return ans;
}
题目描述
求有多少种长度为n的序列A,满足以下条件:
1.1~n这n个数在序列中各出现了一次。
2.若第i个数Ai的值为i,则称i是稳定的。序列恰好有m个数是稳定的。
满足条件的序列可能很多,序列数对109+7取模。
输入
第一行一个数T,表示有T组数据。
接下来T行,每行两个整数n,m。
输出
输出T行,每行一个数,表示求出的序列数
样例输入
复制样例数据
5 1 0 1 1 5 2 100 50 10000 5000
样例输出
0 1 20 578028887 60695423
提示
T=500000,n,m≤106
数据有梯度。
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
#define maxn 1000005
const int mod = 1e9+7;
typedef long long ll;
ll f[maxn],fi[maxn];
ll qpow(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans%mod;
}
void F(){
f[0]=1;
for(int i=1;i<=maxn;i++){
f[i]=f[i-1]*i%mod;
}
}
ll C(ll x,ll y){
ll ans=f[x]%mod*qpow(f[y]*f[x-y]%mod,mod-2)%mod;
return ans;
}
int main()
{
int t;
cin>>t;
F();
fi[0]=1;
fi[1]=0;
fi[2]=1;
for(int i=3;i<=maxn-5;i++){
fi[i]=(i-1)*(fi[i-1]+fi[i-2])%mod;
}
while(t--){
int n,m;
scanf("%d %d",&n,&m);
ll ans=C(n,m)*fi[n-m]%mod;
printf("%lld
",ans);
}
return 0;
}