• bzoj4517[Sdoi2016]排列计数


    bzoj4517[Sdoi2016]排列计数

    题意:

    求有多少种长度为n的序列 A,满足1~n在序列中各出现了一次,且序列恰好有m个数是稳定的(若第i个数A[i]的值为i,则称i是稳定的)。共T组数据,方案数模10^9+7。T=500000,n≤1000000,m≤1000000。
    题解:
    显然结果为C(n,m)*f[n-m],f[n-m]为错排数满足f[i]=(f[i-1]+f[i-2])*(i-1),f[1]=0,f[0]=1。因为n,m过大,求组合数的递推法行不通,因此只能用公式:C(n,m)=n!/(m!*(n-m)!),n!先递推出来,因为最后有除法,故还须求个逆元,刚好模数是质数,所以利用费马小定理,写个快速幂就好了。
    代码:
     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define inc(i,j,k) for(int i=j;i<=k;i++)
     5 #define maxn 1000010
     6 #define mod 1000000007
     7 using namespace std;
     8 
     9 inline int read(){
    10     char ch=getchar(); int f=1,x=0;
    11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    12     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    13     return f*x;
    14 }
    15 long long power(int a,int b){
    16     if(b==0)return 1; if(b==1)return a;
    17     long long c=power(a,b>>1);
    18     if(b&1)return c*c%mod*a%mod;else return c*c%mod;
    19 }
    20 long long a[maxn],b[maxn]; int t,n,m;
    21 long long c(int n,int m){
    22     return a[n]*power(a[n-m]*a[m]%mod,mod-2)%mod;
    23 }
    24 int main(){
    25     a[0]=1; inc(i,1,maxn-10)a[i]=a[i-1]*i%mod; b[0]=1; b[1]=0; inc(i,2,maxn-10)b[i]=(b[i-1]+b[i-2])%mod*(i-1)%mod;
    26     t=read();
    27     while(t--){n=read(); m=read(); printf("%lld
    ",c(n,m)*b[n-m]%mod);}
    28     return 0;
    29 }

    20160814

  • 相关阅读:
    uva299 Train Swapping
    uva 10106 Product
    uva 340 MasterMind Hints
    uva 10115 Automatic Editing
    uva748 Exponentiation
    uva152 Tree's a Crowd
    uva 10420 List of Conquests
    uva 644 Immediate Decodability
    要知其所以然的学习(转载)
    持有书籍统计
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/5778103.html
Copyright © 2020-2023  润新知