zoukankan      html  css  js  c++  java
  • 康拓展开--P5367 【模板】康托展开

    举个栗子大家应该就能懂了:

    我现在生成了1~5的全排列,求数列5  2  3  1  4是第几个

    5:有四个数比他小,他后面还有4个数,所以他的贡献应该是4*4!

    2:有一个数比他小,他后面还有3个数,所以他的贡献应该是1*3!

    3:有两个数比他小,他后面还有两个数,但是其中2在前面出现过了,所以他的贡献应该是1*2!

    1:有零个数比他小,他后面还有一个数,所以他的贡献应该是0*1!

    4:有三个数比他小,他后面还有0个数,但是1 2 3都在前面出现过,所以他的贡献应该是0*0!

    所以数列5  2  3  1  4的前面有4*4!+1*3!+1*2!+0*1!+0*0!个数列

    它本身就是第4*4!+1*3!+1*2!+0*1!+0*0!+1个数列

    如何知道比他小的数字的个数,和树状数组维护逆序对的原理一样,初始时都为1,如果出现过,就-1,求前缀和

    而阶乘我们可以用秦九韶算法优化,比如上面的式子就=((((4*4+1)*3)+1)*2+0)*1+0*1+1

    代码:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 using namespace std;
     5 #define int long long
     6 const int maxn=1e6+10,mod=998244353;
     7 int n;
     8 int a[maxn],tmp[maxn],sum[maxn];
     9 void fix(int x,int k){
    10   for (int i = x;i <= n;i+=i&(-i)) sum[i]+=k;
    11 }
    12 int query(int x){
    13   int res=0;
    14   for (int i = x;i >= 1;i-=i&(-i)) res+=sum[i];
    15   return res;
    16 }
    17 signed main(){
    18   scanf ("%lld",&n);
    19   for (int i = 1;i <= n;i++) fix(i,1);
    20   for (int i = 1;i <= n;i++) scanf ("%lld",&a[i]);
    21   for (int i = 1;i <= n;i++){
    22     tmp[i]=query(a[i]-1);
    23     fix(a[i],-1);
    24   }
    25   int ans=tmp[1]*(n-1);
    26   for (int i = 2;i <= n-1;i++){
    27     ans=ans+tmp[i]; ans=ans%mod;
    28     ans=ans*(n-i); ans=ans%mod;
    29   }
    30   ans=ans+1;ans+=ans*tmp[n]*1;ans=ans%mod;
    31   printf("%lld
    ",ans);
    32   return 0;
    33 }
  • 相关阅读:
    【多视图几何】TUM 课程 第5章 双视图重建:线性方法
    【多视图几何】TUM 课程 第4章 同名点匹配
    【多视图几何】TUM 课程 第3章 透视投影
    SpringMVC配置实例
    sqlserver的触发器练习实例
    zTree学习实例
    浅谈JVM与内存分配
    Ajax的简单实用实例
    Sqlserver事务备份和还原实例
    JQueryEasyUI学习简单Demo
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13757448.html
Copyright © 2011-2022 走看看