程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> [ACM] poj 2369 Permutations (置換群循環節長度)

[ACM] poj 2369 Permutations (置換群循環節長度)

編輯:C++入門知識

Description

We remind that the permutation of some final set is a one-to-one mapping of the set onto itself. Less formally, that is a way to reorder elements of the set. For example, one can define a permutation of the set {1,2,3,4,5} as follows:
\
This recZ喎?http://www.Bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcmQgZGVmaW5lcyBhIHBlcm11dGF0aW9uIFAgYXMgZm9sbG93czogUCgxKSA9IDQsIFAoMikgPSAxLCBQKDMpID0gNSwgZXRjLgo8YnI+CldoYXQgaXMgdGhlIHZhbHVlIG9mIHRoZSBleHByZXNzaW9uIFAoUCgxKSk/IEl0oa9zIGNsZWFyLCB0aGF0IFAoUCgxKSkgPSBQKDQpID0gMi4gQW5kIFAoUCgzKSkgPSBQKDUpID0gMy4gT25lIGNhbiBlYXNpbHkgc2VlIHRoYXQgaWYgUChuKSBpcyBhIHBlcm11dGF0aW9uIHRoZW4gUChQKG4pKSBpcyBhIHBlcm11dGF0aW9uIGFzIHdlbGwuIEluIG91ciBleGFtcGxlIChiZWxpZXZlIHVzKQo8YnI+CjxpbWcgc3JjPQ=="http://www.2cto.com/uploadfile/Collfiles/20140401/20140401093154417.jpg" alt="\">
It is natural to denote this permutation by P2(n) = P(P(n)). In a general form the defenition is as follows: P(n) = P1(n), Pk(n) = P(Pk-1(n)). Among the permutations there is a very important one — that moves nothing:
\
It is clear that for every k the following relation is satisfied: (EN)k = EN. The following less trivial statement is correct (we won"t prove it here, you may prove it yourself incidentally): Let P(n) be some permutation of an N elements set. Then there exists a natural number k, that Pk = EN. The least natural k such that Pk = EN is called an order of the permutation P.
The problem that your program should solve is formulated now in a very simple manner: "Given a permutation find its order."

Input

In the first line of the standard input an only natural number N (1 <= N <= 1000) is contained, that is a number of elements in the set that is rearranged by this permutation. In the second line there are N natural numbers of the range from 1 up to N, separated by a space, that define a permutation — the numbers P(1), P(2),…, P(N).

Output

You should write an only natural number to the standard output, that is an order of the permutation. You may consider that an answer shouldn't exceed 109.

Sample Input

5
4 1 5 2 3

Sample Output

6

Source

Ural State University Internal Contest October'2000 Junior Session


解題思路:

題目要求為給定一個排列 4 1 5 2 3,問經過多少次置換可以重新回到這個排列。

定理:

\

什麼是循環節。。比如

1 2 3 4 5 從上向下看

4 1 5 2 3
1->4->2->1 (1,4,2)為一個循環節,長度為3 3->5->3(3,5)為一個循環節,長度為2 則所求的次數即定理中的k

下面的樣例解釋轉於博客 http://blog.csdn.net/cqlf__/article/details/7910849

分析下樣例
1 2 3 4 5

原始序列: 4 1 5 2 3

2 4 3 1 5
p(p(1))=p(4)=2;
p(p(2))=p(1)=4;
p(p(3))=p(5)=3;
...
...

1 2 5 4 3
p(p(p(1)))=p(2)=1;
p(p(p(2)))=p(4)=2;
p(p(p(3)))=p(3)=5;
...
...

4 1 3 2 5
p(p(p(p(1))))=p(1)=4;
p(p(p(p(2))))=p(2)=1;
p(p(p(p(3))))=p(5)=3;
2 4 5 1 3

1 2 3 4 5

就是兩個循環節(1,2,4) 和(3,5) 我們只要求出lcm(循環節長度)便是其需要移動的次數




代碼:
#include 
#include 
using namespace std;

int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)//求最小公倍數
{
    return a/gcd(a,b)*b;
}

const int maxn=1005;
int num[maxn];
int visit[maxn];

int main()
{
    int n;
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
            cin>>num[i];
        memset(visit,0,sizeof(visit));
        int res=1,flag;
        for(int i=1;i<=n;i++)
        {
            int count=0;//用來記錄每個循環節的長度
            flag=i;//記錄下標
            while(!visit[flag])//沒有被訪問過,不存在於之前的循環節中
            {
                count++;
                visit[flag]=1;
                flag=num[flag];
            }
            if(count)//注意有可能count是0的情況,即外層循環循環到第i個數,而此時第i個數在之前尋找循環節中已經被訪問過
                res=lcm(count,res);
        }
        cout<


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved