CF542C 解题分析
1 题目大意#
1.1 题目翻译:
给定一个值域为 的函数 ,让你求出最小的 ,其中 满足 。
其实我觉得这题你谷翻译十分到位,建议没读懂题的还是去看你谷翻译罢。
1.2 数据范围:
对于 的数据:
1.3 *关于数据范围
这个 其实可以开到 的,但前提是你得加一个高精度。出题人好仁慈,拜谢出题人。
2 解法分析#
发现出现了 这种东西,不难想到建图。
我们可以把 向 连一条有向边。不难发现,整个图被分成了多个连通块,每一个连通块都形似基环树。我们可以把每一个环的大小和一个点到环的最短距离算出来。
现在,我们分两种情况讨论。设答案为 :
-
如果结点 在环中,设这个环大小为 ,那么这个结点必须绕至少 次才能出现相等。所以,。
-
如果结点 不在环上,设这个结点到环的最短距离为 ,那么这个结点只有走至少 次才能到环。所以,。
于是,答案就简单了。我们把所有环的大小取最小公倍数 ,然后算出第二种结点 的最大值 。如果 ,那么就成立;否则,还要用带余除法计算出最小的 ,满足 。此时, 即为答案。
3 AC Code#
代码丑的要死,将就着看吧。
int dfs(int x) {
if (vis[x])
return dis[x];
vis[x] = 1;
dfn[x] = ++ timetmp;
int num = dfs(a[x]);
if (vis[a[x]] == 1)
p = a[x], num = dfn[x] - dfn[p] + 1;
else if (cycle[a[x]] == 1) dis[x] = 1;
else dis[x] = num + 1;
if (p > 0 && vis[p] == 1)
cycle[x] = 1, dis[x] = num;
vis[x] = 2;
return dis[x];
}
void solve() {
cin >> n;
f (i, 1, n)
scanf("%lld", &a[i]);
int k = 1;
f (i, 1, n)
if (!vis[i]) {
p = -1;
dfs(i);
}
f (i, 1, n)
if (cycle[i])
k = k * dis[i] / __gcd(k, dis[i]);
int x = 0;
f (i, 1, n)
if (!cycle[i])
x = max(x, dis[i]);
if (x > k)
k = ((x - 1) / k + 1) * k;
printf("%lld\n", k);
}
作者:DE_aemmprty
出处:https://www.cnblogs.com/aemmprty/p/17491925.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库