HDU-5392-Infoplane in Tina Town

5 篇文章 0 订阅

HDU-5392-Infoplane in Tina Town

传送门

这道题是lcm。只不过是多个数的lcm。

这个题目大意我硬是理解了好久,就很卡。。

题目大意:题目背景是一个游戏,说是你站在当前格子上会给你下一步走的位置。那么转换为我们的抽象含义:给出一组序列。让你恢复初始序列。(即让给定序列的数字恢复到他应该在的位置,比如数字1应该在1的位置,数字5应该在5的位置。)
要分解循环长度。然后找到这些长度的最小公倍数。
我们这里找最小公倍数的方法是分解质因数的方法。
那么什么是分解循环长度?
比如样例:
长度:6
下标:1 2 3 4 5 6
元素:2 1 4 5 6 3
比如我们现在站在下标为1这个格子上,a[1] = 2;给出了下一步走的位置:是2这个格子。所以我们来到了2这个格子。。。然后依次下去走下去。直到走完本次循环。
比如我们的一个循环长度(下面列出的是走的下标):
1 -> 2 -> 1 -> 2-> 1 -> 2…
这就是一个循环。这个循环的长度是2;
3 -> 4 -> 5 -> 6 -> 3 -> 4 -> 5 -> 6…
这也是一个循环。循环长度是4;
我们找到循环长度的最小公倍数是4;
方法:分解质因数;
求解多个数的最小公倍数的方法:
把这些数分解质因数,然后找到公共的质因数,用公共质因数的最高次幂乘以每个数的其他质因数就是这些数的最小公倍数

那么什么是公共质因数的最高次幂。就是这些数的共有的质因数,然后能够除以最多次的那个质因数的次数,就是公共质因数的最高次幂。
比如我们求解14, 16的最小公倍数。
14 = 2 * 7;(2出现了1次,7出现了1次)
16 = 2 * 2 * 2 * 2;(2出现了4次)
公共质因数为:2;
最高次幂为:4;
就是出现次数最多的。

这两部分解决完之后就很好解决了。
num[]数组:下标存储的是因数。里面存的值为出现最多的次数。
我们把那些下标为合数的值赋值为1.(在后面维护答案的时候乘以1是不发生改变的)
cnt保存的是每次求得循环长度。

代码部分:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e6 + 10;
const ll mod = 3221225473;

int t;
int a[N];
int vis[N];
int num[N];
int n;

int main()
{
	cin >> t;
	while (t--)
	{
		scanf ("%d", &n);
		for (int i = 1; i <= n; i++)
		{
			scanf ("%d", &a[i]);
			vis[i] = 0;
			num[i] = 0;
		}
		for (int i = 1; i <= n; i++)
		{
			if (!vis[i])
			{
				int cnt = 0;
				int k = i;
				while (!vis[k])//这部分求的是循环长度
				{
					vis[k] = 1;
					cnt++;
					k = a[k];
				}
				for (int j = 2; j * j <= cnt; j++)
				{
					int top = 0;
					if (!(cnt % j))//这里求的是质因数
					{
						while (!(cnt % j))
						{
							cnt /= j;
							top++;
						}
					}
					num[j] = max(num[j], top);//维护最高次幂的质因数
				}
				if (cnt > 1)//这里就是上面说的方便后面累乘
				{
					num[cnt] = max(num[cnt], 1);															
				}
			}
		}
		ll res = 1;
		for (int i = 2; i <= n; i++)
		{
			while (num[i]--)
			{
				res = res * i % mod;
			}
		}
		cout << res << endl;
	}
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

娃娃酱斯密酱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值