Day4 T1 数列变换

时间:2019-09-13
本文章向大家介绍Day4 T1 数列变换,主要包括Day4 T1 数列变换使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

  小X看到堆成山的数列作业十分头疼,希望聪明的你来帮帮他。考虑数列\(A=\)[\(A_1\)\(A_2\)……\(A_n\)],定义变换f(A,k)=[\(A_2\)\(A_3\)……\(A_k\)\(A_1\)\(A_{k+2}\)\(A_{k+3}\)……\(A_{2k}\)\(A_{k+1}\)……],也就是把A分段,每段k个(最后如果不足k个,全部分到新的一段里,详见样例),然后将每段的第一个移动到该段的最后一个。
  现在,小X想知道 f(f(f(f([1,2,3,⋯,n],2),3),⋯),n)的结果。

输入

输入一行包含一个整数n。

输出

输出一行包含n 个整数,表示最终的数列。

样例

输入 输出
4 4 2 3 1

数据范围

对于60%的数据,1≤n≤\(10^3\)
对于100%的数据,1≤n≤\(10^6\)

题解

  仔细观察可以发现,每次前一段的第一个数移动到了后一段的第一个。
  每次将前一段的第一个数移动到后一段的第一个的位置,那么每次将前一段的第一个数移动到后一段的第一个,最终整个数列总的就移动了n-1次。只需开一个两倍大的数组,再记录当前数列的头部位置即可。
(我这里用了滚动数组,看了一位Dalao的代码,发现只需用swap即可STL大法好

#include<cstdio>
#include<algorithm>
using namespace std;
int n,head,inv=0;
int a[2000010]={0},t[2]={0};

void init(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) a[i]=i;
    head=1;
}

void work(int k){
    for(int i=head;i<=n+head-1;i+=k){
        t[inv]=a[i];
        a[i]=t[inv^1];
        inv^=1;
        if(i+k>n+head-1) a[n+head]=t[inv^1];
    }
}

int main(){
    init();
    for(int i=2;i<=n;i++){
        work(i);
        head++;
    }
    for(int i=head;i<n+head-1;i++) printf("%d ",a[i]);
    printf("%d",a[n+head-1]);
    return 0;
}

原文地址:https://www.cnblogs.com/znk161223/p/11516643.html