【思维·模拟】jzoj3403数列变换 纪中集训提高B组
Description
小X 看到堆成山的数列作业十分头疼,希望聪明的你来帮帮他。考虑数列A=[A1,A2,…,An],定义变换f(A,k)=[A2,A3,.Ak,A1,Ak+2,Ak+3,A2k,Ak+1,…],也就是把a 分段,每段k 个(最后如果不足k 个,全部分到新的一段里,见样例),然后将每段的第一个移动到该段的最后一个。
现在,小 X想知道 f (f (f (f ([1,2,3,⋯,n],2),3),⋯),n)的结果。
Input
输入一行包含一个整数n 。
Output
输出一行包含n 个整数,表示最终的数列。
Sample Input
4
Sample Output
4 2 3 1
【样例说明】
f ([1,2,3,4],2) = [2,1,4,3]
f ([2,1,4,3],3) = [1,4,2,3](3单独被分在一组,移动到组的最后一位,仍然是3)
f ([1,4,2,3],4) = [4,2,3,1]
Data Constraint
对于60%的数据,1≤ n ≤10^3。
对于100%的数据,1≤ n ≤10^6。
考场上只写了60分的暴力分,没有想到什么特别的优化。
万万没想到正解其实很简单,我们发现移动数组这个操作是非常浪费时间的,所以我们就不移它,只移每一段最前面的数,直接开两倍数组把最前面的数往后面搞就可以了。
而且代码量还比暴力少。
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 2000005
#define LL long long
int n,a[MAXN];
int main()
{
scanf("%d",&n);
if(n==1){printf("1\n"); return 0;}
if(n==2){printf("2 1\n"); return 0;}
for(int i=1;i<=n;i++)
a[i]=i;
for(int k=2;k<=n;k++)
{
int i,tmp,past;
for(i=k-1;i+k<=n+k-2;i+=k)//枚举起点
{
tmp=a[i];
if(i!=k-1) a[i]=past;
past=tmp;
}
a[n+k-1]=a[i];
a[i]=tmp;
}
for(int i=n;i<=2*n-1;i++)
printf("%d ",a[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现