Description
开始有一初始数列 a = [ a 1 , a 2 , a 3 , ⋅ ⋅ ⋅ , a n ] a=[a_{1},a_{2},a_{3},···,a_{n}] a=[a1,a2,a3,⋅⋅⋅,an] ,定义 f ( a , k ) = [ a 2 , a 3 , ⋅ ⋅ ⋅ , a k , a 1 , a k + 2 , a k + 3 , ⋅ ⋅ ⋅ , a 2 k , a k + 1 ⋅ ⋅ ⋅ ] f(a,k)=[a_{2},a_{3},···,a_{k},a_{1},a_{k+2},a_{k+3},···,a_{2k},a_{k+1}···] f(a,k)=[a2,a3,⋅⋅⋅,ak,a1,ak+2,ak+3,⋅⋅⋅,a2k,ak+1⋅⋅⋅] ,也就是把 a a a 分段,每段 k k k 个,若最后不足 k k k 个时,将剩下的组成新的一段,每段第一个移成该段最后一个。
求 f ( f ( f ( f ( f ( 1 , 2 , 3 , ⋅ ⋅ ⋅ , n ) , 2 ) , 3 ) , ⋅ ⋅ ⋅ ) , n ) f(f(f(f(f(1,2,3,···,n),2),3),···),n) f(f(f(f(f(1,2,3,⋅⋅⋅,n),2),3),⋅⋅⋅),n) 的结果。
1 ≤ n ≤ 1 0 6 1\leq n\leq 10^{6} 1≤n≤106 。
Solution
考虑使用 模拟 和 找规律 来解题。
操作中是将数列按每 k k k 个为一段,将第一个移到最后一个的位置,其他然后往前补一格。
但我们很快可以发现,有一种等价的做法是:将第 1 1 1 个移到 k + 1 k+1 k+1 个的位置,第 k + 1 k+1 k+1 个移到第 2 k + 1 2k+1 2k+1 的位置,一直到第 x k + 1 xk+1 xk+1 个移到 n + 1 n+1 n+1 的位置,第 2 2 2 个到第 n + 1 n+1 n+1 个组成的序列和之前的做法组成的序列是一样的。
那问题就变成了在数列中移动是 k k k 的倍数加 1 1 1 的数的问题。
然后这道题目就做完了,具体细节详见代码。
Code
#include<cstdio>
int n,a[2000001],an,t;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
a[i]=i;
for(register int i=2;i<=n;i++)
{
an=a[i-1];
for(register int j=2*i-1;j<=n+i-2;j+=i)
{
t=an;
an=a[j];
a[j]=t;
}
a[n+i-1]=an;
}
for(int i=n;i<=2*n-1;i++)
{
printf("%d ",a[i]);
}
return 0;
}