数学【洛谷P4071】 [SDOI2016]排列计数

P4071 [SDOI2016]排列计数

求有多少种长度为 n 的序列 A,满足以下条件:

1 ~ n 这 n 个数在序列中各出现了一次

若第 i 个数 A[i] 的值为 i,则称 i 是稳定的。序列恰好有 m 个数是稳定的

满足条件的序列可能很多,序列数对 10^9+7 取模。

错排+组合数。

首先n-m个元素是完全错排,带公式即可。

剩下的m个是要有序的,也就是从n个选m个。

code:

#include <iostream>
#include <cstdio>

#define int long long

using namespace std;

const int wx=1000007;

const int mod=1e9+7;

inline int read(){
    int sum=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    return sum*f;
}

int T,n,m;
int d[wx],fac[wx],inv[wx];

int ksm(int a,int b){
    int re=1;
    while(b){
        if(b&1)re=re*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return re;
}

void pre(){
    d[0]=1; d[1]=0; d[2]=1;
    for(int i=3;i<=1000000;i++)d[i]=(((i-1)%mod)*((d[i-1]+d[i-2])%mod))%mod;
    fac[0]=1;fac[1]=1;for(int i=2;i<=1000000;i++)fac[i]=i*fac[i-1]%mod;
    inv[1000000]=ksm(fac[1000000],mod-2);
    for(int i=1000000-1;i>=0;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}

int CC(int x,int y){
    if(x<y)return 0;
    return (((fac[x]%mod*inv[y]%mod)%mod)*(inv[x-y]%mod))%mod;
}

int C(int x,int y){
    return d[x-y]*(CC(x,y))%mod;
}

signed main(){
    T=read(); pre();
    while(T--){
        n=read(); m=read();
        printf("%lld\n",C(n,m));
    }
    return 0;
}

转载于:https://www.cnblogs.com/wangxiaodai/p/9891214.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值