引入



这位老爷子就是康托

基本概念

康托展开是一个全排列到一个自然数的双射,常用于构建hash表时的空间压缩。设有n个数(1,2,3,4,…,n),可以有组成不同(n!种)的排列组合,康托展开表示的就是是当前排列组合在n个不同元素的全排列中的名次。

所以,康托展开是为了把一种全排列压缩成一个整数,它的实质是计算当前排列在所有由小到大全排列中的名次,因此是可逆的,称为逆康托展开(这篇博客不会讲)。

基本原理

我们用a[i]表示位于位置i后面的数小于A[i]值的个数。

公式长这样:

\(X=\sum_{i=1}^n a[i]×(n-i)!+1\)

也就是:

\(X = A[0] × (n-1)! + A[1] × (n-2)! + … + A[n-1] × 0!\)

这个算出来的数康拖展开值,是在所有排列次序 - 1的值,因此X+1即为在全排列中的次序,最终输出的应该是X+1

举个栗子:

在(1,2,3,4,5)5个数的排列组合中,计算 34152的康托展开值。

带入上面的公式

X=2*4!+2*3!+0*2!+1*1!+0*0! =>X=61

最后的结果也就是62.

康托展开基础-核心代码

//返回数组a中当下顺序的康托
int cantor(int *a,int n)
{
int ans=0;
for(int i=0;i<n;i++)
{
int x=0,c=1,m=1;
for(int j=i+1;j<n;j++)
{
if(a[j]<a[i])x++;
m*=c;
c++;
}
ans+=x*m;
}
return ans;
}

注意:这个函数返回的是X,输出请输出X+1,理由上面说过了.

康托展开的优化

很明显,上面讲的方法很暴力 需要\(O(n^2)\)的时间才能跑出来。

怎么优化呢?

首先我们可以了解,对于第\(i\)个位置,若该位置的数是未出现在之前位置上的数中第\(k\)大的,那么有\((k-1) \times (N-i)!\)种方案是该位置上比这个排列小的,所以总排名比该排列小。

由此我们可以得到,该排列的排名等于\(\sum_{i=1}^{N}(a[a_i]-1) \times (N-i)!\)

p.s.内层\(a_i\)表示给出的排列中的第i个数,重名不要管因为上文就是用的a数组计排名

阶乘问题因为每次都来计算太费事,所以预处理一下就可以了。

根据思路就可以用树状数组水过去模板了

不会树状数组的向这里看

代码:

#include<bits/stdc++.h>
#define FAST_IN std::ios::sync_with_stdio(false);cin.tie(NULL);
#define MOD 998244353
using namespace std;
long long fac[1000010],a,n,tree[1000001],ans;
int lowbit(int k)
{
return k&-k;
}
long long ask(long long s)
{
long long ans=0;
for(long long i=s;i>=1;i-=lowbit(i))
ans+=tree[i];
return ans;
}
void add(int s,int num)
{
for(long long i=s;i<=n;i+=lowbit(i))
tree[i]+=num;
}
void cal()
{
fac[0]=1;
for(int i=1;i<=n;i++)
{
fac[i]=fac[i-1]*i%MOD;
add(i,1);
}
}
int main()
{
FAST_IN;
cin>>n;
cal();
for(int i=1;i<=n;i++)
{
cin>>a;
ans=(ans+(ask(a)-1)*fac[n-i]%MOD)%MOD;
add(a,-1);
}
cout<<ans+1<<endl;
return 0;
}

模板题传送门

ov.

【算法进阶-康托展开】-C++的更多相关文章

  1. [算法总结]康托展开Cantor Expansion

    目录 一.关于康托展开 1.什么是康托展开 2.康托展开实现原理 二.具体实施 1.模板 一.关于康托展开 1.什么是康托展开 求出给定一个由1n个整数组成的任意排列在1n的全排列中的位置. 解决这样 ...

  2. POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

    http://poj.org/problem?id=1077 http://acm.hdu.edu.cn/showproblem.php?pid=1043 X=a[n]*(n-1)!+a[n-1]*( ...

  3. BZOJ3301 P2524 UVA11525 算法解释康托展开

    这三个题的代码分别对应第二个第一个第三个 在刘汝佳蓝书上我遇到了这个康托展开题. 当时去了解了一下,发现很有意思 百度上的康托展开定义 原理介绍 编辑 康托展开运算 其中, 为整数,并且 . 的意义为 ...

  4. 康托展开&逆展开算法笔记

    康托展开(有关全排列) 康托展开:已知一个排列,求这个排列在全排列中是第几个 康托展开逆运算:已知在全排列中排第几,求这个排列 定义: X=an(n-1)!+an-1(n-2)!+...+ai(i-1 ...

  5. POJ 1077 Eight (BFS+康托展开)详解

    本题知识点和基本代码来自<算法竞赛 入门到进阶>(作者:罗勇军 郭卫斌) 如有问题欢迎巨巨们提出 题意:八数码问题是在一个3*3的棋盘上放置编号为1~8的方块,其中有一块为控制,与空格相邻 ...

  6. 洛谷P2525 Uim的情人节礼物·其之壱 [康托展开]

    题目传送门 Uim的情人节礼物·其之壱 题目描述 情人节到了,Uim打算给他的后宫们准备情人节礼物.UIm一共有N(1<=N<=9)个后宫妹子(现充去死 挫骨扬灰!). 为了维护他的后宫的 ...

  7. HDU_1043 Eight 【逆向BFS + 康托展开 】【A* + 康托展开 】

    一.题目 http://acm.hdu.edu.cn/showproblem.php?pid=1043 二.两种方法 该题很明显,是一个八数码的问题,就是9宫格,里面有一个空格,外加1~8的数字,任意 ...

  8. hihoCoder #1312 : 搜索三·启发式搜索(A*, 康托展开)

    原题网址:http://hihocoder.com/problemset/problem/1312 时间限制:10000ms 单点时限:1000ms 内存限制:256MB   描述 在小Ho的手机上有 ...

  9. HDU1430 BFS + 打表 + 康托展开

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1430 , 一道比较好的题. 这道题要用到很多知识,康托展开.BFS.打表的预处理还要用到一一映射,做完 ...

随机推荐

  1. LC 21. Merge Two Sorted Lists

    题目描述 Merge two sorted linked lists and return it as a new list. The new list should be made by splic ...

  2. Vue基础知识学习(后端)

    ### Vue学习(后端) Vue安装 -引入文件安装,直接在官网下载vue.js引入项目中 -直接引用CDN -NPM安装(构建大型应用使用,在这不用) -命令行工具(构建大型单页应用,在这不用) ...

  3. Python之字符与编码笔记

    概述 类型 str 字符串 bytes 字节 bytearray 字节数组 字符串编码架构 字符集:赋值一个编码到某个字符,以便在内存中表示 编码 Ecoding:转换字符到原始字节形式 解码 Dec ...

  4. 串口(USART)通信-串口通讯协议简介

    物理层:规定通讯系统中具有机械.电子功能部分的特性,确保原始数据在物理媒体的传输.其实就是硬件部分. 协议层:协议层主要规定通讯逻辑,统一收发双方的数据打包.解包标准.其实就是软件部分. 简单来说物理 ...

  5. Tree Generator™ CodeForces - 1149C (线段树,括号序列)

    大意: 给定括号序列, 每次询问交换两个括号, 求括号树的直径. 用[ZJOI2007]捉迷藏的方法维护即可. #include <iostream> #include <algor ...

  6. B+Tree的基本介绍

    概念 特点 B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用B+Tree实现其索引结构. 与B-Tree相比,B+Tree有以下不同点: 每个节点的指针上限为2d而不是2d ...

  7. 【原创】大叔经验分享(88)jenkins假死

    jenkins安装启动后,使用systemctl来进行进程监控 # systemctl enable jenkins 但是还是经常发生jenkins进程挂了,不会自动重启,通过systemctl查看状 ...

  8. 安装theano踩过的坑(gpu)

    参考 http://deeplearning.net/software/theano/install.html TensorFlow出了点问题 python3.7的环境 pip安装 keras已经安装 ...

  9. Android 音频播放速率调整实现

    最近接触到的一个项目, 有音频播放.切换播放速率和拖动进度到某处播放的需求 ,由于之前只是见过并没有尝试过切换播放速率 , 于是开始调研并最终实现,下面简单记录一下这次的调研过程. MediaPlay ...

  10. (转载)小白的linux设备驱动归纳总结(一):内核的相关基础概念---学习总结

    1. 学习总结 小白的博客讲的linux内核驱动这一块的东西比较基础,因此想通过学习他的博客,搭配着看书的方式来学习linux内核和驱动.我会依次更新在学习小白的博客的过程的感悟和体会. 2.1 内核 ...