1 条题解
-
0
自动搬运
来自洛谷,原作者为

yummy
这个人是时代的眼泪,什么也没有留下搬运于
2025-08-24 21:20:47,当前版本为作者最后更新于2018-10-01 11:37:36,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
简单地逛了逛题解区,发现大部分题解分为两种:
next_permutation- 手写
next_permutation
于是,我为了不让题解区太单调,也为了拓宽大家的思维,就经过几分钟的努力,想出了一种与众不同的方法。
Updated on 2022.7.14: 添加 ,增加变进制数加法的讲解。
变进制数
我们的目标是把全排列转化成一个变进制数,以方便我们进行加法。
对于第 根手指,它有 种选择,根据位值原理,要想让每个数对应一个全排列,就要让这一位数是 进制的。那么,整个过程分为三步:
- 将火星数变成变进制数
- 将变进制数加上
- 将变进制数变成火星数
我们来看一个实例: 将 变成变进制数:
- 首位 是 种选择 的第 种,故变为 (从0开始)
- 次位 是 种选择 的第 种,故变为
- 中间位 是 种选择 的第 种,故变为
- 次低位 是 种选择 的第 种,故变为
- 末位 是 种选择 的第 种,故变为
- 最后,排列 变成了
接下来给它加上 变成 ,并处理进位:
- 末位是 进制的,进 得 。
- 次低位是 进制的,满 进一得 。
- 中间位是 进制的,满 进一得 。
- 次位是 进制的,,不进位,得 。
最后将 变回火星数。
- 首位 表示这位应选择 的第 种,即
- 次位 表示这位应选择 的第 种( 被选过了),即
- 中间位 表示这位应选择 的第 种,即
- 次低位 表示这位应选择 的第 种,即
- 末位 表示这位应选择 的第 种,即
所以本题答案为
1452315243。代码 行,应该是除 STL 外较短的了。
#include<bits/stdc++.h> using namespace std; int a[10005]; bool used[10005]={0}; int m,n; int main() { cin>>n>>m; for(int i=1;i<=n;i++) { cin>>a[i]; int x=a[i]; for(int j=1;j<=a[i];j++) x-=used[j]; used[a[i]]=1; a[i]=x-1; } a[n]+=m; for(int i=n;i>0;i--) { a[i-1]+=a[i]/(n-i+1); a[i]%=n-i+1; } memset(used,0,sizeof(used)); for(int i=1;i<=n;i++) { for(int j=0;j<=a[i];j++) if(used[j]) a[i]++; cout<<a[i]+1<<" "; used[a[i]]=1; } return 0; }
这篇题解是我较早时候发的,通过评论区我纠正了举个栗子那个部分的小问题。
现在我也通过评论区知道我这方法叫做康托展开。如果你想了解更多,可以看这篇博客.
- 1
信息
- ID
- 90
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者