蒟蒻养成记——数列变化

xiaoxiao2021-02-28  90

Cycle

【题目描述】

给出一个序列P

定义F(p,k)操作为把p分成若干组,每组k个元素(最后一组可能不够k个元素),然后每组元素整体左移一位。比如p=(1,2,3,4),F(p,2)=(2,1,4,3),F(p,3)=(2,3,1,4)...

现在你需要求出F(F(F(...F([1,2,3,4...,n],2)...),n-1),n)的结果

【输入格式】

一个数字n

【输出格式】

一行n个数字,为F(F(F(...F([1,2,3,4...,n],2)...),n-1),n)的结果

【输入样例】

4

【输出样例】

4 2 3 1

【样例解释】

F([1,2,3,4],2)=[2,1,4,3]

F([2,1,4,3],3)=[1,4,2,3]

F([1,4,2,3],4)=[4,2,3,1]

【数据约定】

40%数据n<=1000

100%数据:1<=n<=10^6

 

【解法】

暴力的时复杂度为O(n^2),所以想想比较玄学的优化。我们发现每次变化的只有n / i 个,所以我们可以只操作那n / i 个.

刚开始我想的是数组模拟链表,后来我发现经过变化后,序列还是连续的(自己画一下就知道了)前一个数刚好放在后一个数的位置

时间复杂度o(n/2+n/3+....+1)

【代码】从后往前

#include<cstdio> #include<cstdlib> #include<iomanip> #include<iostream> #include<algorithm> #include<cstring> using namespace std; int a[2000001]; int i,j,k,m,n,o,p,js,jl,ma,mb; int main() { FILE *fin,*fout; memset(a,0,sizeof(a)); fin=fopen("cycle.in","rb"); fout=fopen("cycle.out","wb"); fscanf(fin,"%d",&n); for(int i=1;i<=n;i++) {    a[i]=i;     }     ma=0;           for (i=2;i<=n;i++) { ma++;    mb=ma+n-(n%i); a[n+ma]=a[mb];    for (j=mb;j>=ma+i;j-=i)a[j]=a[j-i]; }     for(int i=n;i<=n+n-1;i++)fprintf(fout,"%d ",a[i]); fclose(fin); fclose(fout); }

【代码2】从前往后

#include<cstdio> #include<cstdlib> #include<iomanip> #include<iostream> #include<algorithm> #include<cstring> using namespace std; int a[2000001]; int i,j,k,m,n,o,p,js,jl,ma,mb,ii; int main() { FILE *fin,*fout; memset(a,0,sizeof(a)); fin=fopen("cycle.in","rb"); fout=fopen("cycle.out","wb"); fscanf(fin,"%d",&n); for(int iii=1;iii<=n;iii++) {    a[iii]=iii;     }     ma=0;      i=2;j=1;     for(i=2;i<=n;i++)     {     mb=ma;     js=a[mb+1];         int kk=n/i;     for(j=1;j<=kk;j++)     {     jl=a[mb+i+1];     a[mb+i+1]=js;     js=jl;       mb=mb+i;     }     ma=ma++;     if(n%i!=0)     {     a[ma+n]=jl;         }     }     for(ii=n;ii<=n+n-1;ii++)fprintf(fout,"%d ",a[ii]); fclose(fin); fclose(fout); }

转载请注明原文地址: https://www.6miu.com/read-60430.html

最新回复(0)