zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    排列计数

    题目描述

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

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

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

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

    输入输出格式

    输入格式:

     

    第一行一个数 T,表示有 T 组数据。

    接下来 T 行,每行两个整数 n、m。

     

    输出格式:

     

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

     

    输入输出样例

    输入样例#1: 
    5
    1 0
    1 1
    5 2
    100 50
    10000 5000
    输出样例#1: 
    0
    1
    20
    578028887
    60695423

    说明

    测试点 1 ~ 3: $T=1000,n leq 8,m leq 8$;

    测试点 4 ~ 6: $T=1000,n leq 12,m leq 12$;

    测试点 7 ~ 9: $T=1000,n leq 100,m leq 100$;

    测试点 10 ~ 12:$T=1000,n leq 1000,m leq 1000$;

    测试点 13 ~ 14:$T=500000,n leq 1000,m leq 1000$;

    测试点 15 ~ 20:$T=500000,n leq 1000000,m leq 1000000$


      分析:

      一道组合数、错排公式的模板。

      很显然可以推出公式是$D_{n-m} imes C^m_n$,那么我们只要预处理即可。

      错排公式的递推式:$D_n=(n-1) imes (D_{n-1}+D_{n-2})$,组合数的阶乘公式:$C^m_n=frac{n!}{m! imes (n-m)!}$。

      只要预处理$D$数组和数据范围内所有数的阶乘$jc[i]$以及$jc[i]$的逆元$ny[i]$即可。这里求逆元可以直接费马小定理,因为模数是质数。

      Code:

      

    //It is made by HolseLee on 14th Sep 2018
    //Luogu.org P4071
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    typedef long long ll;
    const int N=1e6+7;
    const ll mod=1e9+7;
    int T,n,m;
    ll jc[N],ny[N],d[N];
    
    template<typename re>
    inline void read(re &x)
    {
        x=0; char ch=getchar(); bool flag=false;
        while( ch<'0' || ch>'9' ) {
            if( ch=='-' ) flag=true; ch=getchar();
        }
        while( ch>='0' && ch<='9' ) {
            x=x*10+ch-'0'; ch=getchar();
        }
        flag ? x=-x : 1 ;
    }
    
    inline ll power(ll x,ll y)
    {
        ll ret=1;
        while( y ) {
            if( y&1 ) ret=(ret*x)%mod;
            y>>=1, x=(x*x)%mod;
        }
        return ret;
    }
    
    void ready()
    {
        d[1]=0, d[2]=1, jc[1]=1, ny[1]=1;
        for(int i=3; i<N; ++i) d[i]=((i-1)*(d[i-1]+d[i-2])+mod)%mod;
        for(int i=2; i<N; ++i) {
            jc[i]=((jc[i-1]*i)+mod)%mod;
            ny[i]=power(jc[i],mod-2);
        }
    }
    
    int main()
    {
        read(T); ready();
        while( T-- ) {
            read(n), read(m);
            if( m==n ) puts("1"); 
            else if( m>n ) puts("0");
            else if( m==0 ) printf("%lld
    ",d[n]);
            else {
                printf("%lld
    ",((d[n-m]*(ny[m]*ny[n-m]%mod))%mod*jc[n])%mod);
            }
        }
        return 0;
    }
  • 相关阅读:
    openSUSE 13.1 Milestone 4 发布
    Neo4j 2.0 M4 发布
    iBoxDB for .NET v1.5发布, 移动NoSQL数据库
    GNU libc (Glibc) 2.18 发布
    Android 开源项目维护者宣布退出
    Jeasyframe 开源框架 稳定版 V1.5 发布
    Spring Mobile 1.1.0.RC1 和 1.0.2 发布
    Deis logo 开源PaaS系统 Deis
    EasyCriteria 3.0 发布
    TypeScript 0.9.1 发布,新增 typeof 关键字
  • 原文地址:https://www.cnblogs.com/cytus/p/9645247.html
Copyright © 2011-2022 走看看