题解:
把每一次转换次数变成1,即每一个k,变换的次数为n/k,则复杂度降为n(1/2+1/3+1/4+..+1/n)=0(nlnn),而要做到这一点可以观察到每一次转换,即将每一个序列段的第一位,移到序列段最后一段+1,于是每一次都移一次,从最后一个开始向前操作,最后数组长度会变成2*n-1,输出n到2*n-1个数即是所求
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX=1000010;
int a[MAX*2],n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
a[i]=i;
for(int k=2,cnt=0;k<=n;k++,cnt++)
{
for(int j=n;j>=1;)
{
if(j%k==0)
{
a[j+1+cnt]=a[j+1-k+cnt];
j-=k;
}
else
{
a[j+1+cnt]=a[j/k*k+1+cnt];
j=j/k*k;
}
}
}
for(int i=1;i<=n;i++)
{
if(i==n)
printf("%d\n",a[i-1+n]);
else
printf("%d ",a[i-1+n]);
}
return 0;
}