当前位置: 首页 > news >正文

神秘题

Trick

  1. 排列置换题,考虑转化乘环上移动问题。

题目

精灵之环

假设知道排列 \(p\)

那么把这个排列 \(p\) 的环连出来,环上点的编号是排列的下标,点的值是编号对应的值。

就比如排列 4 1 2 3 的环为:

val: 4  1  2  3  4
id : 1->2->3->4->1...

可以发现把这些环上的值移动一次会使得环上点的编号和值相等,此时就对应排列 \(1,2,3,4,\dots,n\),也就是 \(p_0\)

然后考虑把 \(p_k\) 的环给连出来,现在对于 \(p_k\) 的一个长度为 \(len\) 的环,如果有 \(\gcd(len,k)=1\),那么就可以把这个环上的值移动 \(k\) 次变成编号与值对应相等的环。

如果不满足 \(\gcd(len,k)=1\),那么可以考虑把若干个长度为 \(len\) 的环拼起来,使得 \(\gcd(len\times t,k)=t\)\(t\) 为环的个数),这样也可以使得把这个环上的值移动 \(k\) 次变成编号与值对应相等的环。

所以对于每种长度的环,找到一个最小的 \(t\) 使得 \(\gcd(len\times t,k)=t\),然后把这些环每 \(t\) 个拼一起即可,因为题目满足有解,所以一定能够找到这个 \(t\)

知道了所有环,就可以求出 \(p\) 了。

代码
#include <bits/stdc++.h>void Freopen() {freopen(".in", "r", stdin);freopen(".out", "w", stdout);
}using namespace std;
const int N = 2e5 + 10, M = 2e5 + 10, inf = 1e9, mod = 998244353;int n, k;
int q[N], p[N];vector< int> G[N];
vector< int> cle[N], ans[N];vector< vector< int> > vec[N], V;int vis[N], mp[N], cnt;void dfs( int u, int id) {if (vis[u]) return ;vis[u] = 1, cle[id].push_back(u);for ( auto v : G[u]) dfs(v, id);
}signed main() {ios :: sync_with_stdio(false);cin.tie(0), cout.tie(0);cin >> n >> k;for ( int i = 1; i <= n; i ++)cin >> p[i];for ( int i = 1; i <= n; i ++) G[p[i]].push_back(p[p[i]]);for ( int i = 1; i <= n; i ++)if (! vis[i]) dfs(i, ++ cnt);for ( int i = 1; i <= cnt; i ++) {int len = (int)cle[i].size();vec[len].push_back(cle[i]);mp[len] = 1;}int tot = 0;for ( int len = 1; len <= n; len ++) {if (! mp[len]) continue ;for ( auto v : vec[len]) {V.push_back(v);int siz = (int)V.size() * len;if (__gcd(k, siz) == (int)V.size()) { // 此时 V.size() 就是 t++ tot;ans[tot].resize(siz);for ( int i = 0; i < siz; i ++)vis[i] = 0;// 构造环for ( auto u : V) {int id = 0;for ( int i = 0; i < siz; i ++)if (! vis[i]) {id = i;break ;}for ( auto c : u)ans[tot][id] = c, vis[id] = 1,id = (id + k) % siz;}cnt = 0, V.clear();}}}// 最后在环上面移动一次就是 p(这里默认了环上的点编号与值相等,也就是 p_0 对应的环)for ( int i = 1; i <= tot; i ++) {int len = (int)ans[i].size();for ( int j = 0; j < len - 1; j ++)q[ans[i][j]] = ans[i][j + 1];q[ans[i][len - 1]] = ans[i][0];}for ( int i = 1; i <= n; i ++) cout << q[i] << ' ';cout << '\n';return 0;
}
http://www.zskr.cn/news/6087.html

相关文章:

  • SQL Server 中的 STUFF 函数与FOR XML PATH详解 - 实践
  • 2025/9/16 总结
  • 2025ICPC网络赛第一场(A,B,C,D,G,I,M)
  • Google Maps
  • P4099 [HEOI2013] SAO
  • Linux chronyd 时间同步服务器,命令
  • ubuntu 22.04安装mysql8.0.41(glibc2.17)
  • 【2025-09-15】动起来了
  • 二叉树的层次遍历
  • 写了一个BBP算法的实现库,欢迎讨论
  • 统计建模库 statsmodels(时序单变量数据)
  • C++ std::unordered_map
  • Rust mut
  • 自动感应门的感应雷达怎么选型?
  • 一些寄存器相关的知识
  • 使用HTTPS 服务在浏览器端启用摄像头的方式解析
  • 5分钟SAE极速部署Dify,高效开发AI智能体应用
  • ruoyi-vue初步接触
  • AT_arc180_c [ARC180C] Subsequence and Prefix Sum
  • 如何快速看懂「祖传项目」?Qoder 强势推出新利器
  • 测试不再碎片化:AI智能体平台「项目资料套件」功能上线!
  • 充气泵方案:充气泵用数字传感器有什么好处?
  • mysql查看连接数,从查询到优化
  • Saga分布式事务框架执行逻辑
  • Microsoft AI Genius | 第三集实战课正式开启:用 Copilot Studio 定制你的专属智能体
  • 基于MATLAB的图像融合拼接GUI系统设计
  • Python使用多线程和异步调用
  • 基于MATLAB/Simulink的TI2000系列DSP模型设计
  • 挖矿木马病毒清理手册
  • Python常见函数和代码示例