KSzsh

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

牛牛的构造(构造)

题目链接

题目描述:

请你给出一个长度为 n 的数组 a ,数组 a 中的数是 1n 的排列,即其中每个数的范围都是 [1,n] ,且每个数各不相同。同时使得这个数组恰好存在 k 个二元组 (i,j) ,满足 1i<jn ,
aiaj=2x(xN)。如果不存在一个数组满足条件,输出 1,如果存在多个数组都满足条件,输出任意一个数组即可。(xN)x 表示某个非负整数。

输入描述:

第一行输入两个整数 n,k(1n106,0k109)

输出描述:

输出一行,一个长度为 n 满足条件的数组,两个数之间以一个空格分隔。

样例1:

input:

3 1

output:

1 3 2

说明:

1 3 2 这个数组仅存在一个二元组 (2,3) 满足条件。

a2a3=20

样例2:

input:

1 100

output:

-1

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int k, n;
int a[N];
// b[i]表示i最多能形成多少个二元组
// 即i, i - 1, i - 2,..., 1这样的排列中i能形成多少个二元组
int b[N];
int main()
{
scanf("%d%d", &n, &k);
int num = 0;
// 对数组b进行构造
for(int i = 1; i <= n; i *= 2)
b[i + 1] = 1;
for(int i = 1; i <= n; i ++)
b[i] = b[i - 1] + b[i];
// 对n, n - 1, n - 2,..., 1这样的数组能形成的二元组的数量和相加
// num为这个1到n的排列能形成的最多的二元组的数量
for(int i = 1; i <= n; i ++)
num += b[i];
// num < k代表这个排列不能形成k个二元组
if(num < k)
{
printf("-1");
return 0;
}
// 如果num >= k则可以
// 得到的数组的形式为一个递减区间和一个递增区间
// 则这个数组的能形成的二元组的数量为:
// 递减区间的数能形成的二元组的数量的和
// 递增区间不会形成二元组
// 如:7 6 5 1 2 3 4的二元组的数量为b[7] + b[6] + b[5]
vector<int> dec, inc;
// 从后往前枚举
for(int i = n; i >= 1; i --)
{
// 只要k >= b[i]就把i放入递减区间
if(k >= b[i])
{
k -= b[i];
dec.push_back(i);
}
// 否则就放入递增区间
else
{
inc.push_back(i);
}
}
// 因为是从后往前枚举,最后要将递增区间翻转
reverse(inc.begin(), inc.end());
// 输出递增递减区间
for(auto j : dec)
printf("%d ", j);
for(auto j : inc)
printf("%d ", j);
return 0;
}

posted on   KSzh  阅读(52)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示