随笔- 19  文章- 0  评论- 0  阅读- 838 

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;
}
/*

*/

 

 
 posted on   熙玺  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

Shu-How Zの小窝

Loading...
点击右上角即可分享
微信分享提示