把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P8376 [APIO2022] 排列

题面传送门
这个题感觉看上去很呆呆地亚子。
首先来考虑\(k\leq 90\)的部分分,显然直接放一个长度为\(k\)的下降子序列就好了。
这个信息用的太逊了,发现\(n\leq 120\)\(80\)分感觉就是用\(2\)位数表示一个二进制位,发现可以从高位到低位做,每次放一个最大的数会让答案乘2,放一个最小的数会让答案加一,就可以得到\(91\)分的好成绩。
接下来要把这个\(2\)转化成\(1.5\)了,大概有两种方法:
第一种是换底数,如果换成以4为底用三位表示就可以过,另外一种是\(01\)互换,大概还要做出一个东西是\(\log k+0\)的个数,然后用小的一边跑,也可以做到减半。
第二种发现不太好做因为如果做\(0\)那么要处理减,所以考虑第一种,发现以\(4\)为底的时候余数\(0,1,2\)都是直接按照上面的方法做即可,\(3\)的时候可以借助前面已经有的两位降序,放一个第三大的就好了。
不过理论上卡满好像会到91但是就是过了
code:

#include "perm.h"
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
#define db double
#define lb long db
#define N (2500+5)
#define M (N-5)
#define K (1500+5)
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-9)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
#include <vector>
using namespace std;vector<int> S;

std::vector<int> construct_permutation(long long k);
int H,A[N],x,cnt,Fl;ll k;
std::vector<int> construct_permutation(long long k){
	int i,j;S.clear();Fl=H=cnt=0;while(k) A[++cnt]=k&1,k>>=1;
	for(i=cnt-1;i;i--) {
		++H;S.PB(H-1);
		if(A[i]) {for(j=0;j<H;j++) S[j]++;H++;S.PB(0);Fl++;}
		if(Fl>=5&&i&1) break;
	}
	if(!i) return S;
	for(i--;i;i-=2){
		++H;S.PB(H-1);
		x=A[i]*2+A[i-1];
		if(x==3) {++H;S.PB(H-1);x--;for(j=0;j<H;j++) S[j]>=x&&(S[j]++);H++;S.PB(x);}
		else if(x==2){for(j=0;j<H;j++) S[j]++;H++;S.PB(0);H++;S.PB(H-1);}
		else if(x==1){++H;S.PB(H-1);for(j=0;j<H;j++) S[j]++;H++;S.PB(0);}
		else ++H,S.PB(H-1);
	}
	return S;
}
posted @ 2022-06-04 19:56  275307894a  阅读(43)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end