洛谷 P5367 【模板】康托展开(数论,树状数组)
题目链接
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 【模板】康托展开(数论,树状数组)的更多相关文章
- 洛谷P5069 [Ynoi2015]纵使日薄西山(树状数组,set)
洛谷题目传送门 一血祭 向dllxl致敬! 算是YNOI中比较清新的吧,毕竟代码只有1.25k. 首先我们对着题意模拟,寻找一些思路. 每次选了一个最大的数后,它和它周围两个数都要减一.这样无论如何, ...
- BZOJ3262/洛谷P3810 陌上花开 分治 三维偏序 树状数组
原文链接http://www.cnblogs.com/zhouzhendong/p/8672131.html 题目传送门 - BZOJ3262 题目传送门 - 洛谷P3810 题意 有$n$个元素,第 ...
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
- 洛谷 P4396 (离散化+莫队+树状数组)
### 洛谷P4396 题目链接 ### 题目大意: 有 n 个整数组成的数组,m 次询问,每次询问中有四个参数 l ,r,a,b .问你在[l,r] 的区间内的所有数中,值属于[a,b] 的数的个 ...
- D 洛谷 P3602 Koishi Loves Segments [贪心 树状数组+堆]
题目描述 Koishi喜欢线段. 她的条线段都能表示成数轴上的某个闭区间.Koishi喜欢在把所有线段都放在数轴上,然后数出某些点被多少线段覆盖了. Flandre看她和线段玩得很起开心,就抛给她一个 ...
- 洛谷P3246 [HNOI2016]序列(离线 差分 树状数组)
题意 题目链接 Sol 好像搞出了一个和题解不一样的做法(然而我考场上没写出来还是爆零0) 一个很显然的思路是考虑每个最小值的贡献. 预处理出每个数左边第一个比他小的数,右边第一个比他大的数. 那么\ ...
- 洛谷P4054 [JSOI2009]计数问题(二维树状数组)
题意 题目链接 Sol 很傻x的题.. c才100, n, m才300,直接开100个二维树状数组就做完了.. #include<bits/stdc++.h> using namespac ...
- 【洛谷3527】[POI2011] MET-Meteors(树状数组+整体二分)
点此看题面 大致题意: 一颗星球被分为\(M\)份,分别属于\(N\)个国家,有\(K\)场陨石雨,第\(i\)个国家希望收集\(P_i\)颗陨石,问其至少要在第几次陨石雨后才能达到目标. 关于整体二 ...
- 洛谷CF1030F Putting Boxes Together(树状数组)
题意: 现在有n个物品,第i个物品他的位置在a[i],他的重量为w[i].每一个物品移动一步的代价为他的w[i].目前有2种操作: 1. x y 将第x的物品的重量改为y 2.l r 将编号在 [ l ...
- 洛谷P1527 矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...
随机推荐
- scrapy基础知识之 parse()方法的工作机制思考:
1.因为使用的yield,而不是return.parse函数将会被当做一个生成器使用.scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型: 2.如果是request则加入 ...
- AlwaysOn 执行备份任务
备份 使用维护计划向导创建备份 启动维护计划向导 填入计划名称,选择每项任务单独计划 选择完整备份和清除任务 配置完整备份任务,选择备份数据库 设置备份文件保存位置, 指定压缩备份,设置执行计划时间为 ...
- Java面试题 equals()与"=="的区别?
面试官:请问 equals() 和 "==" 有什么区别? 应聘者: equals()方法用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object ...
- 使用PowerShell比较本地文本文件与Web上的文本文件是否相同
使用PowerShell比较本地文本文件是否相同通常有两种方式:1.通过Get-FileHash这个命令,比较两个文件的哈希是否相同:2.通过Compare-Object这个命令,逐行比较两个文件的内 ...
- CTSC&APIO被教做人记
DAY 0: 早早起来从衡水出发,在去火车站的路上明白了HZOI总是差点误车的真相……上了绿皮火车之后由于没网没流量就开始看政治书应付学考,然而并不是很能看进去,感觉初中学的比高中学的不知道高到哪里去 ...
- c++中利用宏定义简化for循环使用
话不多说,上方法 #define _for(i,a,b) for( int i=(a); i<(b); ++i) #define _rep(i,a,b) for( int i=(a); i< ...
- 深度解密Go语言之channel
目录 并发模型 并发与并行 什么是 CSP 什么是 channel channel 实现 CSP 为什么要 channel channel 实现原理 数据结构 创建 接收 发送 关闭 channel ...
- matlab考试重点详解
此帖是根据期末考试复习重点补充完成, 由于使用word编辑引用图片和链接略有不便, 所以开此贴供复习及学习使用.侵删 复习要点 第一章 Matlab的基本概念,名称的来源,基本功能,帮助的使用方法 1 ...
- java 金额的大小写转换类
/** *金额大小写转换工具类 */ public class MoneyUtil { /** 大写数字 */ private static final String[] NUMBERS = { &q ...
- K-Means(K均值)、GMM(高斯混合模型),通俗易懂,先收藏了!
1. 聚类算法都是无监督学习吗? 什么是聚类算法?聚类是一种机器学习技术,它涉及到数据点的分组.给定一组数据点,我们可以使用聚类算法将每个数据点划分为一个特定的组.理论上,同一组中的数据点应该具有相似 ...