P9578「Cfz Round 1」Permutation
思路
我们需要尽量让相邻两个数的和的最大值减最小值最小。
先思考如何让最大值最小。
对于 n,两侧最小也必须要放 1 和 2。所以最大值至少也是 n+2。
同时,我们再思考 1 周围能摆什么,因为不能让最小值太小,我们需要放比较大的,也就是 n 和 n−1。
这样来看的话,最小值最大是 n。
所以除了 n=1 或者 n=2 的特殊情况外,我们要构造的序列的值最小是 2。
再来思考一下能不能达成 2,对于大于 ⌈n2⌉ 的 i,他的两侧可以放 n−i+2 和 n−i+1。对于小于 ⌊n2⌋ 的 i,他的两侧可以放 n−i+1 和 n−i。可以验证这样摆放再处理一下 n 为偶数的特殊情况,就可以使值为 2。
那么,我们在思考如何生成序列。
首先可以确定 n 的位置,在它的两侧放上 1 和 2,再在 1 旁边的空位摆上 n−1,在 2 旁边的空位摆上 n−2⋯。
可以发现,这种构造方式可以换一种描述方式。
先摆一个 n,然后每次在两侧加数,第 2×k−1 次加数会在两侧分别加 2×k−1 和 2×k,第 2×k 次加数会在两侧分别加 n−2×k+1 和 n−2×k。
如果最后还剩一个也就是 n 为偶数时,可以把剩下的数放在任意两端。
AC code
#include<bits/stdc++.h> using namespace std; int n,a,b[1000005],now,cnt=1,mi,ma,ha; int main() { scanf("%d",&n),now=n,mi=1,ma=n-1,ha=ceil(1.0*n/2),b[ha]=n;//懒得算每次摆的是什么数,于是就用两个变量存一下,ha记录中间的位置 while(cnt<=(n-1)/2) if(cnt&1) b[ha-cnt]=mi,b[ha+cnt]=mi+1,mi+=2,++cnt; else b[ha-cnt]=ma,b[ha+cnt]=ma-1,ma-=2,++cnt;//按照上面的方法摆放数字 if(n%2==0) b[n]=mi;//n为偶数时的情况 for(int i=1;i<=n;++i) printf("%d ",b[i]);//输出 return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】