/*
题意:
1、数组循环右移,
解题:
1、先算出最大公约数,从n - m到n - m + d - 1枚举起始位
2、计算下一个位置,当前位置,temp存当前位置元素,不断开始较短
learn && wrong:
1、从n - m到n -1会出错的,只要到n - m + d - 1即可
2、修正m,因为有可能m比n大,没必要浪费那么多次
3、一趟循环停止,是下一个位置是初始点,就停止
4、核心代码要好好看一下,
先计算pos,temp,next,之后就是三行核心代码而已;
5、next的处理很有意思,不是单纯减m,还要加上n,再余上n;
*/
#include <iostream>
using namespace std;
int gcd(int a, int b){
if(b == 0) return a;
else return gcd(b, a % b);
}
int main(int argc, char** argv) {
int a[110];
int n,m,temp,pos,next;
//temp为临时变量,pos存放当前处理的位置,next为下一个要处理的位置
scanf("%d%d",&n,&m);
for(int i = 0;i < n;++i){
scanf("%d", &a[i]);
}
m = m % n; //修正m,当m大于n时,可以少执行很多次
if(m != 0) { //如果m==0,直接输出数组即可,不需要执行这部分
int d = gcd(m,n);
for(int i = n - m;i < n - m + d;++i){ //枚举一个最大公约数的范围
temp = a[i]; //当前位置的元素暂存
pos = i; //记录当前处理的位置
do{
//计算下一个要处理的位置
next = (pos - m + n) % n;
//如果下一个位置不是初始点
//则把下一个位置的元素复制给当前的处理位置
if(next != i) a[pos] = a[next];
else a[pos] = temp; //把一开始拿走的元组赋值给最后这个额空位
pos = next; //传递位置
} while(pos != i); //循环直到当前处理位置回到初始位置结束
}
}
for(int i = 0;i < n;++i){
printf("%d", a[i]);
if( i < n - 1) printf(" ");
}
return 0;
}
网友评论