• 题解 P5367 【【模板】康托展开】


    P5367 【模板】康托展开

    感觉这题难度大概在绿题到蓝题之间qwq

    一、洛谷日报[yummy]浅谈康托展开

    如我想知道321是{1,2,3}中第几个小的数可以这样考虑 :

    第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2× 2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1× 1!=1 所以小于321的{1,2,3}排列数有2×2!+1×1!=5个。所以321是第6个小的数。 2 ×2!+1× 1!+0× 0!就是康托展开。

    再举个例子:1324是{1,2,3,4}排列数中第几个大的数:第一位是1小于1的数没有,是0个 0× 3! 第二位是3小于3的数有1和2,但1已经在第一位了,所以只有一个数2,1×2! 。第三位是2小于2的数是1,但1在第一位,所以有0个数 0×1! ,所以比1324小的排列有0×3!+1× 2!+0×1 !=2个,1324是第三个小数。(摘自百度)

    暴力做法

    //n表示全排列长度
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        int x=a[i];
        for(int j=1;j<=a[i];j++)
            x-=used[j];
        //used[j]表示j是否用过(1用过,0没用)
        used[a[i]]=1;
        a[i]=x-1;
    }
    

    二、优化

    “我们看到,刚才的方法有两重循环,时间复杂度为 O(N^2) ,找左侧用过的数的数量很费时间。

    只要把used函数用线段树或树状数组维护区间和,就可以只花log的时间就求出左侧小于自己的数的个数了。” (摘自日报)

    三、代码

    #include<cstdio>
    using namespace std;
    #define N 1000001
    int n,tr[N];
    long long ans,fac[N];
    inline void add(int x,int k) {
    	for (; x<=n; x+=x&-x) tr[x]+=k;
    }
    inline int query(int x) {
    	int t=0;
    	for (; x; x-=x&-x) t+=tr[x];
    	return t;
    }
    int main() {
    	scanf("%d",&n);
    	fac[0]=1;
    	for (int i=1; i<=n; i++) {
    		fac[i]=fac[i-1]*i%998244353;
    		add(i,1);
    	}
    	for (int i=1,x; i<=n; i++) {
    		scanf("%d",&x);
    		ans=(ans+(query(x)-1)*fac[n-i])%998244353;
    		add(x,-1);
    	}
    	printf("%lld",ans+1);
    	return 0;
    }
    

    四、拓展:逆康托展开

    例 {1,2,3,4,5}的全排列,并且已经从小到大排序完毕

    (1)找出第96个数

    首先用96-1得到95

    用95去除4! 得到3余23

    有3个数比它小的数是4

    所以第一位是4

    用23去除3! 得到3余5

    有3个数比它小的数是4但4已经在之前出现过了所以第二位是5(4在之前出现过,所以实际比5小的数是3个)

    用5去除2!得到2余1

    有2个数比它小的数是3,第三位是3

    用1去除1!得到1余0

    有1个数比它小的数是2,第二位是2

    最后一个数只能是1

    所以这个数是45321(摘自百度)

  • 相关阅读:
    linux addr2line 定位so库崩溃位置
    转:关于Android机型适配这件小事儿
    转:android studio 改编译区背景色
    转:ios review推送与执行
    k2pdfopt下载页
    转:让kindle更好的支持pdf
    转:各种文本格式转换的网站
    转: iOS崩溃堆栈符号表使用与用途
    转: 腾讯Bugly干货分享:Android应用性能评测调优
    转: git的图文使用教程(巨详细)
  • 原文地址:https://www.cnblogs.com/Randolph68706/p/11200202.html
Copyright © 2020-2023  润新知