P9345 题解(2023 激励计划评分 6)

有一定思维含量的思维题(蒟蒻想了 2020 分钟)。

至少这个难度评的比较正确。

思路

显然的在前 nn 个数中理论上最大的公约数只会是 n2\lfloor\dfrac{n}{2}\rfloor,因此 kk 的理论上界即为 n2\lfloor\dfrac{n}{2}\rfloor

考虑对于 kn2k\le \lfloor\dfrac{n}{2}\rfloor 的情况。

显然 (a,2a)=a(a,2a)=a,考虑对于前 nn 个数,将其分成 (1,2)(2,4)(3,6)(1,2)(2,4)(3,6)\dots 的形式。

然而,这样的序列会有重复,例如:1,2,2,4,3,6,4,8,5,10,1,2,2,\color{red}4,\color{black}3,6,\color{red}4\color{black},8,5,10,\dots

考虑将 (a,2a,22a,23a,)(a,2a,2^2a,2^3a,\dots) 拼成一组,即 1,2,4,8,16,32,64,,3,6,9,12,1,2,4,8,16,32,64,\dots,3,6,9,12,\dots,其中 aa 为奇数或 22

然而这样可能会超 kk 的限制,怎么办呢?

考虑 bb 序列,在上面这种情况下一定出现 1,2,4,8,,k,,11,2,4,8,\dots,k,\dots,1

而前 2k2k 个数可以产生 kk 个最大公约数,因此,我们把 [2k+1,n][2k+1,n] 区间内的数全部倒序排列在 11 的后面,即 1,n,n1,,2k+1,2,4,8,1,n,n-1,\dots,2k+1,2,4,8,\dots

因为 2k+12k+1 一定为奇数,不会和 22 产生最大公约数。

所以这道题就解完了,代码如下。

#include<bits/stdc++.h>
using namespace std;
int T,n,k,a[300005];
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&k);
		if(k>n/2){
			printf("No\n");
			continue;
		}
		cout<<"Yes\n1 ";
		for(int i=n;i>=2*k+1;i--)cout<<i<<' ';
		for(int i=1;i<=2*k;i+=2){
			for(int j=max(2,i);j<=k*2;j*=2)cout<<j<<' ';
		}
		cout<<endl;
	}
}
posted @   Weslie_qwq  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示