• [gym100956]Problem J. Sort It! BIT+组合数


    source : Pertozavodsk Winter Training Camp 2016 Day 1: SPb SU and SPb AU Contest, Friday, January 29, 2016

    url:https://codeforces.com/gym/100956/attachments

    -----------------------------------------------------

    题意:

    有一个1~n的全排列p1~pn,问有多少个长度为n的数组,满足

    1.数组中每个元素均为1~n的正整数

    2.按照全排列的顺序,i从1到n,依次将数组中等于pi的元素拿出来放在新数组末端,完成后新数组为有序的。

    -----------------------------------------------------

    题解:

     

    样例

    3

    2 1 3

    含1个不同元素的数组:

      1:1个

      2:1个

      3:1个

    含2个不同元素的数组:

      2,3:2^3-1个

      1,3:2^3-1个

     

    解法:

    求出原排列中长度为1~n的上升子序列有多少个,记为len[i];

    求出严格含1~n个不同元素的n位的数组有多少种,记为f[i];

    则ans = sigma(len[i]*f[i])

    求len[i]:递推,已知以第j位为结尾的长度为x的上升子序列有sum_prelen[j]个,则以第i位为结尾长度为x+1的上升子序列数量=sigma(sum_prelen[1~i-1])。用树状数组维护。

    求f[i]:f[i]=i! - sigma(f[1~i-1])

    -------------------------------------------------

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long LL;
     5 const int N=2010;
     6 const LL mod=(LL)1e9+7;
     7 int n;
     8 LL c[N],sum_prelen[N],len[N],val[N],jc[N],f[N]; 
     9 
    10 void readin(LL &x)
    11 {
    12     x=0;bool f=0;char ch=getchar();
    13     while(!isdigit(ch)) {
    14         f|=(ch=='-');
    15         ch=getchar();
    16     }
    17     while(isdigit(ch)) {
    18         x=(x<<3)+(x<<1)+ch-48;
    19         ch=getchar();
    20     }
    21     if(f) x=-x;
    22 }
    23 
    24 void add(LL x,LL d){
    25     for(int i=x;i<=n;i+=(i&(-i))) c[i]=(c[i]+d)%mod;
    26 }
    27 LL getsum(LL x){
    28     LL ans=0;
    29     for(int i=x;i>=1;i-=(i&(-i))) ans=(ans+c[i])%mod;
    30     return ans;
    31 }
    32 
    33 LL mypow(LL x,LL y){
    34     LL ans=1;
    35     while(y)
    36     {
    37         if(y&1) ans=ans*x%mod;
    38         x=x*x%mod;
    39         y>>=1; 
    40     }
    41     return ans;
    42 }
    43 
    44 LL mod_inverse(LL x,LL n){
    45     return mypow(x,n-2);
    46 }
    47 
    48 LL cal_C(LL x,LL y){
    49     // C(x,y)=y!/(x!(y-x)!)
    50     return jc[y] * mod_inverse(jc[x],mod) % mod * mod_inverse(jc[y-x],mod) % mod;    
    51 }
    52 
    53 int main()
    54 {
    55     freopen("a.in","r",stdin);
    56     scanf("%d",&n);
    57     for(int i=1;i<=n;i++) readin(val[i]);
    58     for(int i=1;i<=n;i++) sum_prelen[i]=1;
    59     len[1]=n;
    60     for(int i=2;i<=n;i++) 
    61     {
    62         len[i]=0;
    63         for(int j=1;j<=n;j++) c[j]=0;
    64         for(int j=1;j<=n;j++) 
    65         {
    66             LL sum_nowlen=getsum(val[j]-1);
    67             len[i]=(len[i]+sum_nowlen)%mod;
    68             add(val[j],sum_prelen[j]);
    69             sum_prelen[j]=sum_nowlen;
    70         }
    71     // for(int j=1;j<=n;j++) printf("%lld ",len[j]);printf("
    ");
    72     }
    73     
    74     jc[0]=1;for(int i=1;i<=n;i++) jc[i]=(jc[i-1]*((LL)i))%mod;
    75     f[0]=0;
    76     LL ans=0;
    77     for(int i=1;i<=n;i++)
    78     {
    79         f[i]=mypow(i,n);
    80         for(int j=1;j<i;j++)
    81             f[i]=((f[i]-cal_C(j,i)*f[j]%mod)%mod+mod)%mod;
    82         ans=(ans+len[i]*f[i]%mod)%mod;
    83     }
    84 
    85     printf("%I64d
    ",ans);
    86     return 0;
    87 }

     

  • 相关阅读:
    Swift 设置navigation左右两侧按钮
    Tab Bar Controller和Navigation Controller混合使用详细教程
    导航栏控制器和标签栏控制器(UINavigationController和UITabBarController)混用
    UIViewController、UINavigationController与UITabBarController的整合使用
    iOS开发UI篇—UIWindow简单介绍
    mod_wsgi + pymssql通路SQL Server座
    UVA 11464 Even Parity(递归枚举)
    iOS kvc
    数据的同步为每个站点创建触发器同步表
    精彩编码 【进制转换】
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/10507374.html
Copyright © 2020-2023  润新知