• 洛谷 P4071 [SDOI2016]排列计数


    首先一看应该是组合数的问题,但我们选出m个数之后,其他的数就不能再排在它原本的位置,所以又需要错排求出方案数。

    错牌公式递推式:

    d[2]=1,d[0]=1,d[1]=0。d[i]=(i-1)*(d[i-1]+d[i-2])

    又由乘法原理可得出总方案数。

    注意:阶乘,逆元,错排都要预处理出来,否则T到飞起。

    未预处理代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    int T;
    long long n,m;
    long long d[maxn];
    const int mod=1e9+7;
    long long ksm(long long a,long long b){
        long long base=1;
        while(b){
            if(b&1) base=base*a%mod;
            b>>=1;
            a=a*a%mod;
        }
        return base;
    }
    long long C(long long n,long long m){
        if(n<m) return 0;
        long long a=1,b=1;
        for(long long i=n-m+1;i<=n;i++){
            a=a*i%mod;
        }
        for(long long i=1;i<=m;i++){
            b=b*i%mod;
        }    
        return a*ksm(b,mod-2)%mod;
    }
    void cp(){
        d[0]=1;
        d[2]=1;
        for(int i=3;i<=1000000;i++){
            d[i]=(i-1)*(d[i-1]+d[i-2])%mod;
        }
    }
    int main(){
        scanf("%d",&T);
        cp();
        while(T--){
            scanf("%lld%lld",&n,&m);
            printf("%lld
    ",C(n,m)*d[n-m]%mod);
        }
        return 0;
    }

    预处理过后:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e6+7;
    int T;
    long long n,m;
    long long d[maxn];
    long long inv[maxn];
    long long f[maxn];
    const int mod=1e9+7;
    long long ksm(long long a,long long b){
        long long base=1;
        while(b){
            if(b&1) base=base*a%mod;
            b>>=1;
            a=a*a%mod;
        }
        return base;
    }
    long long C(long long n,long long m){
        if(n<m) return 0;
        long long a=1,b=1;
        for(long long i=n-m+1;i<=n;i++)    a=a*i%mod;
        for(long long i=1;i<=m;i++)    b=b*i%mod;
        return a*ksm(b,mod-2)%mod;
    }
    void cp(){
        d[0]=1;
        d[2]=1;
        for(int i=3;i<=1000000;i++)    d[i]=(i-1)*(d[i-1]+d[i-2])%mod;
    }
    void jc(){
        f[1]=1;
        f[0]=1;
        for(int i=2;i<=1000000;i++)    f[i]=f[i-1]*i%mod;
    }
    void ny(){
        inv[0]=ksm(f[0],mod-2);
        for(int i=1;i<=1000000;i++)    inv[i]=ksm(f[i],mod-2)%mod;
    }
    void work(){
        printf("%lld
    ",(f[n]*inv[m]%mod*inv[n-m]%mod*d[n-m])%mod);
    }
    int main(){
        scanf("%d",&T);
        cp();
        jc();
        ny();
        while(T--){
            scanf("%lld%lld",&n,&m);
            work();
        }
        return 0;
    }
  • 相关阅读:
    用U3D寻找看电视的感觉!!
    MipMap
    什么是 A 轮融资?有 B轮 C轮么?
    Java写的斗地主游戏源码
    sqlserver sp_spaceused用法
    SQL中的全局变量和局部变量(@@/@)
    SQL2008数据库导出到SQL2000全部步骤过程
    生成Insert语句的存储过程
    物理机连接虚拟机数据库
    配置sql server 2000以允许远程访问
  • 原文地址:https://www.cnblogs.com/LJB666/p/11011705.html
Copyright © 2020-2023  润新知