[hihoCoder 太閣最新面經算法競賽6] 數組重排(N個數的最小公倍數)

描述

小Hi想知道,如果他每次都按照一種固定的順序重排數組,那麼最少經過幾次重排之後數組會恢復初始的順序?

具體來講,給定一個1 - N 的排列 P,小Hi每次重排都是把第 i 個元素放到第 Pi個位置上。例如對於 P = (2, 3, 1),假設初始數組是(1, 2, 3),重排一次之後變爲(3, 1, 2),重排兩次之後變爲(2, 3, 1),重排三次之後變回(1, 2, 3)。

被排數組中的元素可以認爲是兩兩不同的。

輸入

第一行一個整數 N ,代表數組的長度。 (1 ≤ N ≤ 100)

第二行N個整數,代表1 - N 的一個排列 P 。

輸出

輸出最少重排的次數。

樣例輸入
3
2 3 1
樣例輸出
3

題解:求每個數跳到原來位置的最小跳數,循環節。再求這N個跳數的最小公倍數。注意使用long long 型!

#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
#include<cstdio>
#include<unordered_map>
#include<unordered_set>
#include<cmath>
#include<climits>
using namespace std;
long long gcd(long long a, long long b)
{
   if (a < b)
      swap(a, b);
   if (b == 0)
      return a;
   else return gcd(b, a%b);
}
long long lcm(long long a, long long b)
{
    return a*b/gcd(a, b);
}
int main()
{
    int n;
    scanf("%d",&n);
    int a[101],num[101];
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
    }
    if(n==1) {
        printf("0\n");return 0;
    }
    for(int i=0;i<n;i++) {
        num[i]=0;
        if(a[i]-1==i) continue;
        int cur=i;
        while(true) {
            cur=a[cur]-1;
            num[i]++;
            if(cur==i) break;
        }
    }
    long long t=1;
    for(int i=0;i<n;i++) {
        if(num[i]==0) continue;
        t=lcm(t,num[i]);
    }
    cout<<t<<endl;
    return 0;
}


發佈了81 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章