51nod 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示例
4
1 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;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值