题目链接

https://www.luogu.org/problem/P5367

什么是康托展开

百度百科上是这样说的:

 
康托展开是一个全排列到一个自然数的双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。

是不是讲得很精(meng)致(bi)呢?

我看了无数篇博客,终于明白了一点点。

其实,康托展开就是求一个全排列在所有全排列中字典序排名第几

举个例子:

比如说n=3的一个全排列:2 1 3 它的排名是3。

我们列出所有的全排列:

1 2 3

1 3 2

2 1 3

2 3 1

3 1 2

3 2 1

显然,2 1 3在里面字典序排名第三。

暴力求法(基本思路)

首先我们用a[i]表示原数的第i位在当前未出现的元素中是排在第几个

比如说  "2 3 4 1"

a[1]=2    a[2]=2    a[3]=2    a[4]=0

拿a[2]举例子,到第二位时,未出现的数字有1,3,4,显然3排在第二位上,所以a[2]=2。

然后我们想,在前k-1位相等的情况下,a[k]具有什么意义?比当前情况字典序小的全排列数有多少呢?

显然是  a[k]*(k-1)!  (注意阶乘的优先级比乘法运算高)  哪里显然了QAQ?

好像这叫做乘法原理来着(蒟蒻记不清楚了)

a[k]是第k位的比原排列小的数字数量,而第k-1~n位无论是什么数一定小于原数列,而且每一位都要用掉一个数字,所以就是a[k]*(k-1)*(k-2)*(k-3)*……*2*1。

最后把这些小于原排列的排列数量加起来,最后在+1就是原数列的排名。

放公式:ans=a1*0+a2*(2-1)!+a3*(3-1)!+……+an*(n-1)!+1。

时间复杂度为O(n^2)

优化

  • 先预处理1到n的阶乘
  • 用树状数组来维护有多少个未出现的比自己小的数(单点修改,区间查询)——一开始所有点都修改为1,然后每遇到一个点,就修改为0,最后查询1~s[k-1]有多少个1就行了(s为原数列)。

当然了,也可以用万能的线段树(只不过常数比较大罢了)

AC代码

 #include<iostream>
#include<cstdio>
using namespace std;
const int mod=;
const int maxn=;
int ss[maxn],a[maxn],s[maxn],n;
inline int lowbit(int x){
return x&(-x);
}
void update(int id,int x){
for(int i=id;i<=n;i+=lowbit(i)){
s[i]+=x;
}
}
int query(int id){
int res=;
for(int i=id;i>;i-=lowbit(i)){
res+=s[i];
}
return res;
}
long long ans,jc[maxn];
int main()
{
cin>>n;
jc[]=;
for(int i=;i<n;i++) jc[i]=jc[i-]*i%mod;
for(int i=;i<=n;i++) scanf("%d",&ss[i]);
for(int i=;i<=n;i++) update(ss[i],);
for(int i=;i<=n;i++){
update(ss[i],-);
a[n-i+]=query(ss[i]);
}
for(int i=;i<=n;i++) ans=(ans+(long long)a[i]*jc[i-]%mod)%mod;
cout<<ans+;
return ;
}

洛谷 P5367 【模板】康托展开(数论,树状数组)的更多相关文章

  1. 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)

    洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...

  2. BZOJ3262/洛谷P3810 陌上花开 分治 三维偏序 树状数组

    原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 洛谷P3810 题意 有$n$个元素,第 ...

  3. [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)

    [NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...

  4. 洛谷 P4396 (离散化+莫队+树状数组)

    ### 洛谷P4396  题目链接 ### 题目大意: 有 n 个整数组成的数组,m 次询问,每次询问中有四个参数 l ,r,a,b .问你在[l,r] 的区间内的所有数中,值属于[a,b] 的数的个 ...

  5. D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]

    题目描述 Koishi喜欢线段. 她的条线段都能表示成数轴上的某个闭区间.Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了. Flandre看她和线段玩得很起开心,就抛给她一个 ...

  6. 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)

    题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...

  7. 洛谷P4054 [JSOI2009]计数问题(二维树状数组)

    题意 题目链接 Sol 很傻x的题.. c才100, n, m才300,直接开100个二维树状数组就做完了.. #include<bits/stdc++.h> using namespac ...

  8. 【洛谷3527】[POI2011] MET-Meteors(树状数组+整体二分)

    点此看题面 大致题意: 一颗星球被分为\(M\)份,分别属于\(N\)个国家,有\(K\)场陨石雨,第\(i\)个国家希望收集\(P_i\)颗陨石,问其至少要在第几次陨石雨后才能达到目标. 关于整体二 ...

  9. 洛谷CF1030F Putting Boxes Together(树状数组)

    题意: 现在有n个物品,第i个物品他的位置在a[i],他的重量为w[i].每一个物品移动一步的代价为他的w[i].目前有2种操作: 1. x y 将第x的物品的重量改为y 2.l r 将编号在 [ l ...

  10. 洛谷P1527 矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...

随机推荐

  1. C语言学习书籍推荐《Practical C++ Programming》下载

    下载链接 :点我 C++ is a powerful, highly flexible, and adaptable programming language that allows software ...

  2. 《转载黑马教程》HTML&&CSS讲义0,,包含教程_仅供参考

    今日内容 1. web概念概述 2. HTML web概念概述 * JavaWeb: * 使用Java语言开发基于互联网的项目 * 软件架构: 1. C/S: Client/Server 客户端/服务 ...

  3. 2. 软件数据流图(DFD)

    数据流图,简称DFD,是SA方法中用于表示系统逻辑模型的一种工具,它以图形的方式描绘数据在系统中流动和处理的过程,由于它只反映系统必须完成的逻辑功能,所以它是一种功能模型. 下图是一个飞机机票预订系统 ...

  4. QQ Music 音乐插件DFX unable to open skin configration 的解决方法

    设置 C:\Program Files (x86)\Tencent\QQMusic\Plugins\Dfx\dfx_skin.txt  它的权限 允许程序读取执行

  5. 掌握简单的Makefile文件编程

    Makefile描述整个程序的编译.链接规则 其中还包括了工程中用到的那些源文件及需要产生的目标文件 1)Makefile编程规则 目标(唯一):依赖(可多个) 命令... 伪目标 .PHONY:cl ...

  6. Spark学习之RDD

    RDD概述 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合 ...

  7. android实现倒计时,最简单实现RecyclerView倒计时+SwipeRefreshLayout下拉刷新

    先上效果图: RecyclerView + SwipeRefreshLayout 实现倒计时效果 MainActivity.java package top.wintp.counttimedemo1; ...

  8. C 单链表 实现约瑟夫环

    list.h #ifndef _List_H #define _List_H typedef int ElementType; struct Node; typedef struct Node *Pt ...

  9. Java、Java SE、Java Web和Java EE的区别

    刚接触Java对这些概念上的东西有点模糊,查了很多资料,想把它分享出来,要是哪里不对请大家指正(^_^) 1.Java 毫无疑问这就是门语言和C.C++.C#一样没什么好说的. 2.Java SE和J ...

  10. ThinkPHP 5.0 控制器-》请求-》数据库

    ThinkPHP 5.0 控制器->请求->数据库 控制器总结 无需继承其他的类(若继承了Think/Controller,可直接调用view函数渲染模板),位置处于application ...