2020-02-09

/*
题意:
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 
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;
}

你可能感兴趣的:(2020-02-09)