冒泡排序 - 结论

本文探讨了一种特定的排序算法及其在排列组合问题中的应用。通过分析算法的行为,我们得出一个结论,即给定一个排列,可以通过计算每个位置后面有多少个数字比当前数字小来确定执行该算法后的迭代次数。基于此,文章提出了一种解决方案,用于找到所有可能排列中,执行上述代码后迭代次数为特定值的第k小排列。
摘要由CSDN通过智能技术生成

题目大意:有这样一个排序:

for(cnt=0;!_sorted_(a,n);cnt++)
    for(int i=n-1;i;i--) if(a[i]>a[i+1]) swap(a[i],a[i+1]);

给定n,问在所有排列p中,第k小的满足执行上述代码后cnt=m的排列是啥。n<=20。
题解:结论是,给定一个排列,那个cnt就是,对每个位置求后面有多少个数字比这个数字小,的max。f(n,m)表示n个数cnt不超过m的方案数是小学生计数。然后逐位枚举确定即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define lint long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int del[30],ans[30];
inline lint fac(int n,lint ans=1) { rep(i,1,n) ans*=i;return ans; }
inline lint _pow_(int a,int b,lint ans=1) { rep(i,1,b) ans*=a;return ans; }
inline lint f(int n,int m) { return (n<=m)?fac(n):_pow_(m+1,n-m)*fac(m); }
inline int kth(int k,int p=1) { for(;k-(!del[p]);p++) k-=!del[p];return p; }
int main()
{
    int n,m,has_mp1=0;lint k;scanf("%d%d%lld",&n,&m,&k);
    if(m==0) { rep(i,1,n) printf("%d ",i);return !printf("\n"); }
    rep(i,1,n) rep(j,1,min(n-i+1,m+1))
    {   has_mp1|=(j==m+1);lint cnt=f(n-i,m)-(has_mp1==0)*f(n-i,m-1);
        if(k>cnt) k-=cnt;else { del[ans[i]=kth(j)]=1;break; }    }
    rep(i,1,n) printf("%d ",ans[i]);return !printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值