康托展开(Cantor Expansion)

2023-12-03 04:36
文章标签 展开 康托 expansion cantor

本文主要是介绍康托展开(Cantor Expansion),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【康托展开简介】
康托展开(Cantor Expansion)是一种特殊的哈希函数,是一个相对快速的判重方法,其时间复杂度为O(n^2),其中 n 是集合中元素的个数。康托展开能够判重,依据的是一个集合各元素产生的全部排列中各个排列的位序 id。而位序 id 的计算公式如下:
id=a[n]\times(n-1)!+...+a[i]\times(i-1)!+...+a[2]\times1!+a[1]\times0!
其中,a[i] 的值为某个排列中第 i 位右边各位中
字典序小于第 i 位的字符的个数,且0≤a[i]<i,1≤i≤n。
利用此公式时,约定
长度为n的某个排列,其下标由左至右依次为 n~1

【康托展开习题】
例如,判断
7698 是 {6, 7, 8, 9} 的全排列中的第几大数(位序)的过程如下:
(0)为了利用上述公式,约定排列 7698 的下标从左至右依次为4, 3, 2, 1 (
下标从1开始),a[i] 的值为某个排列中第 i 位右边各数中小于第 i 位的数的个数。
(1)在排列 7698 中,第
4位为7,其右边各位比它小的数有a[4]=1个,为6。根据上文公式,贡献1×(4-1)!=6。
(2)在排列 7698 中,第
3位为6,其右边各位比它小的数有a[3]=0个。根据上文公式,贡献0×(3-1)!=0。
(3)在排列 7698 中,第
2位为9,其右边各位比它小的数有a[2]=1个,为8。根据上文公式,贡献1×(2-1)!=1。
(4)在排列 7698 中,第
1位为8,其右边各位比它小的数有a[1]=0个。根据上文公式,贡献0×(1-1)!=0。
求和,得 1×(4-1)!+0×(3-1)!+1×(2-1)!+0×(1-1)!=6+0+1+0=7。即比排列 7698 位序小的排列有 7 个,也即排列 7698 的位序为8。

【康托展开代码】

#include <bits/stdc++.h>
using namespace std;const int maxn=100;
int f[maxn];void fact(int n) {f[0]=1;for(int i=1; i<=n; i++)f[i]=f[i-1]*i;
}int cantor(string s){int ans=1;int len=s.length();for(int i=0;i<len;i++){int cnt=0;for(int j=i+1;j<len;j++){if(s[i]>s[j]) cnt++;}ans+=cnt*f[len-i-1];}return ans;
}int main() {int n;cin>>n;fact(n);string s;cin>>s;cout<<cantor(s)<<endl;return 0;
}/*
in:
10
34152
out:
62
-------
in:
5
bac
out:
3
-------
in:
5
2ac
out:
1
*/


【参考文献】
https://zhuanlan.zhihu.com/p/643917734
https://baike.baidu.com/item/%E5%BA%B7%E6%89%98%E5%B1%95%E5%BC%80/7968428?fr=ge_ala




 

这篇关于康托展开(Cantor Expansion)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/448086

相关文章

通知Notification(可展开的大布局)使用,适配android8.0

补充修正: 2018-11-07 问题:Notification PendingIntent失效,每个通知都响应第一个PendingIntent https://blog.csdn.net/u013370255/article/details/83791750 2018-08-16 问题:app版本更新,通知形式显示安装包下载进度 https://blog.csdn.net/u01337025

vue3 行点击事件 table 树 点击行展开

需求:每次需要点击左侧小按钮才可以展开不方便,提出点击行就展开 el-table 添加 ref="tableDeptRef"@row-click="handleRowClick" 方法 const tableDeptRef = ref()/**行点击事件 */const handleRowClick=(row)=> {tableDeptRef.value.toggleRowExpa

zm-tree-org 数据量过大时,全部展开后,根节点点击收缩,树形消失

zm-tree-org 数据量过大时,全部展开后,根节点点击收缩,树形消失 <zm-tree-orgref="tree"@on-expand="onExpand"</zm-tree-org>export default {methods: {onExpand(e, data) {<!-- 当为根节点,且根节点为闭合时 -->if (data.root === true && data.expa

二叉树展开为列表(LeetCode)

题目 给你二叉树的根结点 root ,请你将它展开为一个单链表: 展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 解题 class TreeNode:def __init__(self, val=0, left=None, right=None):self.va

24.9.1(康托展开)

上星期三: 补 24牛客多校 二 C                                                  牛客传送门 思路: 赛时写模拟写的很臭,如果用dp写就很方便 代码如下: const int N=2e6+10;const int mod=1e9+7;ll n;char s[N][2];int dp[N][2];void solve(){c

leetcode 114:二叉树展开为链表

二叉树的题,使用递归的方式 TreeNode *last(TreeNode*root){while(root->right!=NULL){root=root->right;}return root;}TreeNode *fla(TreeNode *root){if(root==NULL)return NULL;if(root->left==NULL&&root->right==NULL)re

求幂级数展开的部分和 / 求分数序列前N项和 / 特殊a串数列求和

习题4-2 求幂级数展开的部分和   (20分) 已知函数e^xe​x​​可以展开为幂级数1+x+x^2 /2! + x^3 /3! + \cdots + x^k /k! + \cdots1+x+x​2​​/2!+x​3​​/3!+⋯+x​k​​/k!+⋯。现给定一个实数xx,要求利用此幂级数部分和求e^xe​x​​的近似值,求和一直继续到最后一项的绝对值小于0.00001。 输入格式:

JQ点击展开二级菜单

JQuery控制点击展开二级菜单,以下为测试代码: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <html>      <head>          <title>JQ点击展开二级菜单</title>  <script class="jquery library" src="jquery-

dom练习题-全选反选、可展开子菜单、事件冒泡、二级联动、表格增删、定时器、多事件绑定

checkbox全选反选可展开菜单事件冒泡二级联动菜单表格增删定时器多事件绑定 checkbox全选、反选 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>作业分解小礼包</title><style></style><script>// 全选function checkAll(

android 折叠屏展开收起监听

折叠屏在展开和收起时,屏幕的物理尺寸会发生变化。你可以通过注册一个ComponentCallbacks2的实例来监听屏幕大小的变化。这个接口提供了onConfigurationChanged(Configuration newConfig)方法,当设备的配置发生变化时(包括屏幕大小和方向)会调用此方法。 public class MyActivity extends AppCompatAct