zoukankan      html  css  js  c++  java
  • bzoj4517(错排+组合)

    求有多少种长度为 n 的序列 A,满足以下条件:
    1 ~ n 这 n 个数在序列中各出现了一次
    若第 i 个数 A[i] 的值为 i,则称 i 是稳定的。序列恰好有 m 个数是稳定的
    满足条件的序列可能很多,序列数对 10^9+7 取模。

    Input

    第一行一个数 T,表示有 T 组数据。
    接下来 T 行,每行两个整数 n、m。
    T=500000,n≤1000000,m≤1000000

    Output

    输出 T 行,每行一个数,表示求出的序列数

    Sample Input

    5
    1 0
    1 1
    5 2
    100 50
    10000 5000

    Sample Output

    0
    1
    20
    578028887
    60695423


    设选定的组合为C(m,n)即总在i位置上的数,那么其余(n-m)必须全不在其位置上即求错排数,
    由乘法原理的ans=C(m,n)*f(n-m);
    组合数公式C(m,n)=n!/m!(n-m)!,
    错排公式为f(n)=f(n-1)*n+(-1)^n;
    预处理出组合数与错排数,最后用乘法逆元计算即可
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    const int maxn=1000000+10;
    const long long mod=1e9+7;
    
    long long a[maxn],f[maxn];
    
    long long pow(long long x,long long y){
              long long ans=1;
              for (;y;y>>=1){
                if(y&1) ans=ans*x%mod;
                x=x*x%mod;
              }
        return ans%mod;
    }
    
    int main(){
        a[0]=1;
        for (int i=1;i<=1000000;i++) a[i]=a[i-1]*i%mod;
        f[0]=1;
        for (int i=1;i<=1000000;i++){
            f[i]=f[i-1]*i%mod;
            if(i&1) f[i]=(f[i]-1)%mod;
            else f[i]=(f[i]+1)%mod;
        }
        int n,m;
        int t;
        scanf("%d",&t);
        for (int i=1;i<=t;i++){
            scanf("%d%d",&n,&m);
            printf("%lld
    ",((a[n]*f[n-m])%mod*pow(a[m]*a[n-m]%mod,mod-2))%mod);
        }
    return 0;
    }
  • 相关阅读:
    js的浅拷贝与深拷贝
    用Nodejs连接MySQL(原文链接)
    HTML5交互性图表库
    GitHub Desktop离线安装包
    docker--Dockerfile--sonarqube
    docker --Nexus仓库
    docker --Dockerfile--一些语法
    zookeeper 四字命令
    docker --swarm创建一个集群
    docker --swarm启动2375端口监听
  • 原文地址:https://www.cnblogs.com/lmjer/p/9320579.html
Copyright © 2011-2022 走看看