首页 > 其他分享 >杂项之 - 康托展开

杂项之 - 康托展开

时间:2024-10-09 21:21:35浏览次数:6  
标签:排列 ee ll 杂项 int 展开 康托

在洛谷上闲逛时无意中看到了这个东东,顺便学了一下

Part1 康托展开是什么

康拓展开是一种将排列映射为一个自然数的双射

康托展开可以用来求一个 \(1\sim n\) 的任意排列的排名。

Part2 康托展开的公式

对于一个排列 \(a_1 \dots a_n\)
把 \(1\sim n\) 的所有排列按字典序排序,这个排列的位次就是它的排名。

他的排名为 $$ \sum_{i=1}^{n} b_{i}*(n-i)+1 $$

其中 \(b_{i}\) 表示在所以还未出现过的数之中有多少个比这个数小

证明如下

设有排列 \(p=a_1,a_2 \dots a_n\) ,那么对任意字典序比 \(p\) 小的排列,一定存在 \(i\) ,使得其前 \(i-1 (1 \le i <n )\) 位与 \(p\) 对应位相同,第 \(i\) 位比 \(p_i\) 小,后续位随意。于是对于任意 \(i\) ,满足条件的排列数就是从后 \(n-i+1\) 位中选一个比 \(a_i\) 小的数、并将剩下 \(n-i\) 个数任意排列的方案数,即为 \(b_i*(n-1)!\) .遍历 \(i\) 即得总方案数 为 $ \sum_{i=1}^{n} b_{i}*(n-i) $ 再加1即为排名。

实现

阶乘预处理一下即可
求 \(b_{i}\) 若使用暴力 总的复杂度是 \(O(n^2)\)
若使用树状数组 总的复杂度是 \(O(n \log n)\)

实现代码如下

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) (-x) & x
const ll mod_ = 998244353;
ll bit[1000010];
int n;
void change(int x, ll delt)
{
    while (x <= n)
    {
        bit[x] += delt;
        x += lowbit(x);
    }
}
ll query(int x)
{
    ll insid = 0;
    while (x)
    {
        insid += bit[x];
        x -= lowbit(x);
    }
    return insid % mod_;
}
ll jie[1100001];
int a[1014514];
void init()//预处理阶乘
{
    jie[0] = 1;
    for (ll oo = 1; oo <= (ll)n; oo++)
    {
        jie[oo] = (jie[oo - 1] * oo) % mod_;
        jie[oo] %= mod_;
    }
}
ll conto()//康托展开
{
    for (int yy = 1; yy <= n; yy++)//加入所有数
    {
        change(a[yy], 1);
    }
    ll insid = 0;
    for (int ww = 1; ww <= n; ww++)
    {
        insid += (query(a[ww] - 1) * jie[n - ww] % mod_) % mod_;//计算排名
        change(a[ww], -1);//将这个数从未出现过的数中删去
        insid %= mod_;
    }
    insid++;
    return insid % mod_;
}
int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    init();
    for (int ee = 1; ee <= n; ee++)
    {
        cin >> a[ee];
    }
    cout << conto();
    return 0;
}

标签:排列,ee,ll,杂项,int,展开,康托
From: https://www.cnblogs.com/sea-and-sky/p/18455194

相关文章

  • .NET高级调试 - 代码审查以及杂项命令
    简介代码审查就是观察代码,代码形态分为三种C#代码>IL代码》汇编代码。通过代码审查,可以从原始代码的字节流中推测出逻辑详情高级调试本质上属于逆向分析,更多的是以汇编为主。反汇编代码u(unassemble)命令u把字节流反汇编为汇编指令还有一个变种ub,uf。u是向下反汇编,ub是向......
  • 杂项乱写 9.29
    因为没有模拟赛,所以考虑捡捡之前漏下的小点。注:LCA之后的讲解中可能会出现一些自由的文字,酌情阅读。dfs序求LCA倍增LCA的常数还是过于大了,虽然好记但会导致我们在一些数据奇异的题中比其它方式求LCA的人的得分要低。所以就有了这个用dfs序求lca的高科技,在时间效率......
  • 【已解决】ElementPlus 的 el-menu 组件如何用 js 控制展开某个子菜单,并在其他组件中
    文章目录需求几次探索官网寻找线索(解决办法)需求我如何用代码来实现ElementPlus的菜单的展开和收缩呢?几次探索尝试通过找到节点之后,使用click事件,失败了//伪代码如下consthandleFindNodeAndClick=()=>{console.log('handleFindNodeAndClick');......
  • Javascript 中的展开和休息运算符及其示例
    剩余和扩展运算符是javascript中强大的功能,允许您更有效地处理数组、对象和函数参数。它们都使用相同的语法(...),但用途不同。休息操作员(...)剩余运算符用于将所有剩余元素收集到数组中。它通常用在函数参数中来处理可变数量的参数。休息运算符示例:functionsum(......
  • JavaScript 中的展开和休息运算符
    零食故事:假设您有一篮子零食:constsnacks=['apple','banana','chocolate'];登录后复制现在,您想与您的朋友分享这些零食。但你不是把整个篮子都给他们,而是把每件零食都拿出来,一一递给他们:console.log(...snacks);//output:applebananachocolate登录后复制...(摊开)操作符就......
  • 『杂项』Linux 常用指令
      不会吧不会吧不会还有Oier不会Linux指令要写一篇博客记一下  今年S组人数骤增,遂ctrl+cv出本篇博客以获得两分(Linux常用指令文件和目录管理命令ls:列出当前目录中的文件和子目录。pwd:显示当前工作目录的路径。cd:切换工作目录。mkdir:创建新目录。rmdi......
  • 杂项——矩阵加速(进阶)
    前言:在之前已经学习过矩阵快速幂的用法,那些只是基础。在ICPC中大多数难度较高,且并不是简单的只需要常数的矩阵或者简单的图上问题,而是结合dp方程去推导出来转移矩阵。trick:例题:链接:https://ac.nowcoder.com/acm/contest/88880/E来源:牛客网给出两个整数\(n,k\),有一个正整数......
  • 力扣热题100 - 二叉树:二叉树展开为链表
    题目描述:题号:114给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。解题思路:思路一:前序遍历后......
  • 记录一些很酷的套路,有时间再展开写
    标了*的是我自己胡出的Ad-hoc东西。图论树两个点集\(S\capT=\emptyset\)分别有直径\(d_S=(u_S,v_S),d_T=(u_T,v_T)\),那么必然有\(d_{S\cupT}=(u,v),u,v\in\{u_S,v_S,u_T,v_T\}\)。题。图优化建图固定长度分块。*题。前缀和。*题。倍增。*题。计数容斥......
  • 【可变参模板】基类参数包的展开
    一、基类参数包的展开1.1基类参数包的展开C++C++C++是一个支持多继承的语言,因此继承的类也可以是一个基类的......