数组重排 hiho一下第167周
来源:互联网 发布:mac bootcamp磁盘权限 编辑:程序博客网 时间:2024/06/06 17:32
题意:小Hi想知道,如果他每次都按照一种固定的顺序重排数组,那么最少经过几次重排之后数组会恢复初始的顺序?
具体来讲,给定一个1 - N 的排列 P,小Hi每次重排都是把第 i 个元素放到第 Pi个位置上。例如对于 P = (2, 3, 1),假设初始数组是(1, 2, 3),重排一次之后变为(3, 1, 2),重排两次之后变为(2, 3, 1),重排三次之后变回(1, 2, 3)。
被排数组中的元素可以认为是两两不同的。
思路:用暴力试了下超时,所以想其他方法。我们能从排列 P 中看到循环。例如 P = (2, 3, 1),第一位的数移到第二个位置,第二个数移到第三个位置,第三个数移到第三个位置,这样就有一个循环:1->2->3->1。在其他例子中也可能不止有一个循环,我们只要去求这些循环的最小公倍数就行了。
代码:
#include<cstdio>#include<cstring>#include<cstdlib>#include<stack>#include<queue>#include<utility>#include<vector>#include<cmath>#include<set>#include<map>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;int N;int p[110];bool vis[110];int GetGcd(int a, int b){ if(a<b) swap(a, b); return b==0? a:GetGcd(b, a%b);}int Cal(int a, int b){ return a*b/GetGcd(a, b);}int main(){ //freopen("in.txt", "r", stdin); while(scanf("%d", &N) == 1){ memset(vis, false, sizeof(vis)); for(int i=0; i<N; i++){ scanf("%d", &p[i]); } int ans = 1; for(int i=0; i<N; i++){ if(!vis[i]){ vis[i] = true; int tmp = p[i]-1; int tmpans = 1; while(!vis[tmp]){ vis[tmp] = true; tmp = p[tmp]-1; tmpans++; } ans = Cal(ans, tmpans); } } printf("%d\n", ans); } return 0;}
阅读全文
0 0
- hiho一下第167周数组重排
- 数组重排 hiho一下第167周
- hiho一下 第167周
- hiho一下 第143周 hiho密码
- hiho一下 第141周
- hiho一下 第139周
- hiho一下第143周
- hiho一下 第145周
- hiho一下 第175周
- hiho一下 第174周
- hiho一下第56周 高斯消元
- hiho一下 第113周 Fibonacci (dp)
- [hiho一下 第128周] 后缀自动机
- [hiho一下 第129周] 后缀自动机
- [hiho一下 第130周] 后缀自动机
- hiho一下 第140周 清理海报
- hiho一下 第139周 买零食
- hiho一下 第139周 买零食
- C中4大跳转语句的区别
- stringstream和char在一起时需要注意
- HDU
- mount.nfs: an incorrect mount option was specified
- 递归与分治策略-2.9.2线性时间选择(取中位数的中位数基准)(第k小问题)
- 数组重排 hiho一下第167周
- 记录我的Java学习经历(1)
- 【QT】对象模型(对象树)
- HDU
- 阿里iconfont官网提供的矢量图标用法介绍
- 网狐荣耀版棋牌中心服务器显示“服务启动失败”的原因
- 运维之系统服务篇------2.linux扩展应用 、 vim编辑技巧 、 发布网络YUM源 、 源码编译安装
- HTTP协议学习笔记
- Linux常用操作命令(一)