51nod 1473-等幂映射(循环节)

来源:互联网 发布:java linklist方法 编辑:程序博客网 时间:2024/06/05 19:16
1473 等幂映射
题目来源: CodeForces
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注

等幂映射是这样定义的,对于一个映射 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(k1)(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。


Input
单组测试数据。第一行包含一个整数 n (1 ≤ n ≤ 200)。第二行给出 f(1), f(2), ..., f(n) (1 ≤ f(i) ≤ n)。
Output
输出最小满足条件的k。
Input示例
41 2 2 4
Output示例
1
System Message (题目提供者)
C++的运行时限为:1000 ms ,空间限制为:131072 KB 示例及语言说明请按这里

 允许其他 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;}


原创粉丝点击