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); }