【t013】无聊的军官

Time Limit: 1 second
Memory Limit: 32 MB

【问题描述】

每个学年的开始,高一新生们都要进行传统的军训。今年有一个军训教官十分奇怪,他为了测试学员们的反应能力,每次吹哨后学员们都会变换位置。每次左数第I位学员都会站到第ai个位置,经过若干次之后,队伍又会回到原来的样子。你的任务是计算n个人的队伍至少经过多少次之后,队伍恢复到原来样子。

【输入格式】

输入文件的第一位包含一个整数N(0<N10000),表示队伍的人数。
接下来N行,每行一个正整数ai表示左起第i个人接下来出现在左起第ai个位置上。

【输出格式】

仅包括一行,一个正整数M,表示军官居最少的吹哨次数。

【输入样例1】

5
2
3
4
5
1

【输出样例1】

5

【数据规模】

对于30%的数据,有N ≤100;
对于100%的数据,有N ≤10000;
对于全部数据,答案均在64位整数范围之内。

【题目链接】:http://noi.qz5z.com/viewtask.asp?id=t013

【题意】

中文题..

【题解】

那个变化位置的序列最后肯定能够形成若干个环的;
每个环的大小就是每个人回到原来位置所需要的步骤数;
那么求这几个环的大小的最小公倍数就好了;
这里我先把环的大小这些数字质因数分解一下;
然后按照每个因数出现次数最多的,作为这个因数的出现次数;
然后每个因数^(因数的出现次数)全部乘起来就好;
先求gcd再相乘除它也能求最小公倍数;
但好像会超时.
(没看到题目下面的数据范围,写了个高精度…)

【完整代码】

#include <cstdio>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int MAXN = 1e4+100;

int a[MAXN],n;
bool bo[MAXN];
vector <int> v,what,zhi;
int num[MAXN],ans[MAXN],al;

bool is(int x)
{
    double t = x;
    int len = int(sqrt(t));
    rep1(i,2,len)
        if (x%i==0)
            return false;
    return true;
}

int main()
{
    //freopen("F:\rush.txt","r",stdin);
    rei(n);
    rep1(i,1,n)
        rei(a[i]);
    rep1(i,2,n)
        if (is(i))
            zhi.pb(i);
    rep1(i,1,n)
        if (!bo[i])
        {
            int j = i,cnt = 0;
            while (!bo[j])
            {
                bo[j] = true;
                cnt++;
                j = a[j];
            }
            v.pb(cnt);
        }
    int len = v.size();
    rep1(i,0,len-1)
    {
        int now = 2,x = v[i],ii = 0,len2 = zhi.size();
        while (ii<=len2-1 && now<=x)
        {
            now = zhi[ii];
            if (x%now==0)
            {
                int cnt = 0;
                while (x%now==0)
                {
                    cnt++;
                    x/=now;
                }
                if (num[now]==0)
                {
                    num[now] = cnt;
                    what.pb(now);
                }
                else
                    num[now] = max(num[now],cnt);
            }
            ii++;
        }
    }
    al = 1;
    ans[1] = 1;
    len = what.size();
    rep1(i,0,len-1)
    {
        int len2 = num[what[i]];
        rep1(j,1,len2)
        {
            int x = 0;
            rep1(k,1,al)
            {
                ans[k]= ans[k]*what[i]+x;
                x = ans[k]/10;
                ans[k] = ans[k]%10;
            }
            while (x>0)
            {
                al++;
                ans[al] = x;
                x = ans[al]/10;
                ans[al] = ans[al]%10;
            }
        }
    }
    rep2(i,al,1)
        printf("%d",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626638.html