Codeforces Round 992 (Div. 2) C题解析
题目描述🥰
题目思路😀
对于这道题来说,因为需要判断是否有k个最大值,所以我们首先需要考虑最大值的排列有多少种
Q1:最大值的排列到底有多少种?
我们可以假设现在已经构造好了 x+1 到 n 的排列方式,考虑 x 可以插入到哪些位置,如果我们放到排列的中间的话,那么我们就会影响到原来取成x+1的值,所以当我们把x放到排列的头部或者尾部,这样就会对原来的值影响更小一点。
总共n个数,我们需要对1~n-1进行决策,决定这个数到底放到头部还是放到尾部,每一个数有两种选择,所以总共有2(n-1)种排列方式,所以当k>=2(n-1)的时候就返回-1
Q2:怎么判断这个数是放到首部还是尾部?
我们可以对k进行二进制拆分,因为这个k的二进制表示就像是状态压缩dp里面的状态表示,k的二进制里面的每一位就对应了n-1个数字的选择方式,对于k二进制的每一位的0/1,实际就对应了这个数字应该放在头部还是放到尾部,如果为1,就说明这个放置方式是把这个数字放到尾部,因为把数字放到尾部的字典序明显比把数字放到头部的字典序要大,如在5 4 中放 3, 5 4 3的字典序明显比 3 4 5的字典序要更大。而如果是0,也是同理。
实现的数据结构选择
因为我们需要对于答案进行头尾部的插入,所以我们可以选择deque(双端队列)来方便我们对于答案的构造。
AC代码🧠
// Problem: C. Ordered Permutations
// Contest: Codeforces - Codeforces Round 992 (Div. 2)
// URL: https://codeforces.com/contest/2040/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define debug1(a) cout << #a << '=' << a << endl;
#define debug2(a, b) cout << #a << " = " << a << " " << #b << " = " << b << endl;
#define debug3(a, b, c) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << endl;
#define debug4(a, b, c, d) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << " " << #d << " = " << d << endl;
#define debug5(a, b, c, d, e) cout << #a << " = " << a << " " << #b << " = " << b << " " << #c << " = " << c << " " << #d << " = " << d << " " << #e << " = " << e << endl;
#define vec(a) \
for (int i = 0; i < a.size(); i++) \
cout << a[i] << ' '; \
cout << endl;
#define darr(a, _i, _n) \
cout << #a << ':'; \
for (int ij = _i; ij <= _n; ij++) \
cout << a[ij] << ' '; \
cout << endl;
#define endl "\n"
#define pow pim
int pim(int a,int k)
{
int res=1;
if(a==0)return 0;
while(k)
{
if(k&1)res=(int)res*a;
k>>=1;
a=(int)a*a;
}
return res;
}
#define fi first
#define se second
#define caseT \
int T; \
cin >> T; \
while (T--)
#define int unsigned long long
// #define int __int128
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 99999999;
// const int N = ;
void solve()
{
int n,k;
cin>>n>>k;
k--;
//如果k大于等于2^(n-1),那么就是没有解的,同时防止数据范围溢出,我们需要判断(n-1)是否小于64
if (n - 1 < 64 && k >= (1ULL << (n - 1))) {
cout << "-1"<<endl;
return;
}
deque<int>q;
q.push_back(n);
for(int i=n-1;i>0;i--)
{
if(k&1)q.push_back(i);
else q.push_front(i);
//不断右移来判断
k>>=1;
}
for(auto x:q)cout<<x<<" ";
cout<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
caseT
solve();
return 0;
}
/*
*/
分类:
codeforces
标签:
codeforces
, 算法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】