等幂映射是这样定义的,对于一个映射 g : {1,2,...,n} → {1,2,...,n} ,对于所有的 x∈ {1,2,...,n} , g(g(x))=g(x)始终成立。
f(k)(x) 表示将映射f作用于x上k次的结果。一般的, f(1)(x) = f(x) , f(k)(x) = f(f(k−1)(x)) 对于所有的k>1成立。
现在给定一个映射 f : {1,2,...,n} → {1,2,...,n} 。你的任务是寻找最小的k使得 f(k)(x) 是一个等幂映射。
样例解释:这个例子中 f(x) = f(1)(x) 已经是一个等幂映射,因为他已经满足定义: f(f(1))=f(1)=1, f(f(2))=f(2)=2, f(f(3))=f(3)=2,f(f(4))=f(4)=4。
单组测试数据。 第一行包含一个整数 n (1 ≤ n ≤ 200)。 第二行给出 f(1), f(2), ..., f(n) (1 ≤ f(i) ≤ n)。
输出最小满足条件的k。
4 1 2 2 4
1
允许其他 AC 的用户查看此代码,分享代码才能查看别人的代码并有机会获得勋章
感觉51nod题目翻译有点问题,然后上cf看了一下,懂了题目的意思,题目就是让求f(i)能否经过k次的操作回到f(i).....
题目意思很明确,就是求出所有f(i)的循环节,然后求一波最小公倍数就OK了,但是我们要注意‘6’这种情况,故可以额外开一个
数组保存多余的最长长度,然后让lcm向上取整就好。
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<string>
#include<math.h>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long ll;
#define inf 1000000000
#define mod 1000000007
#define maxn 1006000
#define PI 3.1415926
#define lowbit(x) (x&-x)
#define eps 1e-9
int a[205], b[205];
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
return gcd(y, x%y);
}
ll lcm(ll x, ll y)
{
return x*y / gcd(x, y);
}
int main(void)
{
int n, i, j;
ll ans = 1, mx = 0, tmp;
scanf("%d", &n);
for (i = 1;i <= n;i++)
scanf("%d", &a[i]);
for (i = 1;i <= n;i++)
{
memset(b, 0, sizeof(b));
j = i;b[a[i]] = 1;
while (1)
{
int nxt = a[j];
if (b[a[nxt]])
{
tmp = b[a[j]] + 1 - b[a[nxt]];
if (mx < b[a[nxt]])
mx = b[a[nxt]];
break;
}
b[a[nxt]] = b[a[j]] + 1;
j = nxt;
}
ans = lcm(ans, tmp);
}
tmp = ans;
while (ans < mx)
ans += tmp;
printf("%lld\n", ans);
return 0;
}