这道题非常无厘头!
题目描述:
每个学年的开始,高一新生们都要进行传统的军训。今年有一个军训教官十分奇怪,他为了测试学员们的反应能力,每次吹哨后学员们都会变换位置。每次左数第I位学员都会站到第ai个位置,经过若干次之后,队伍又会回到原来的样子。你的任务是计算n个人的队伍至少经过多少次之后,队伍恢复到原来样子。
输入格式:
输入文件的第一位包含一个整数N(0<N10000),表示队伍的人数。
接下来N行,每行一个正整数ai表示左起第i个人接下来出现在左起第ai个位置上。
输出格式
仅包括一行,一个正整数M,表示军官最少的吹哨次数。
样例:
输入:
5
2 3 4 5 1
输出:
5
分析:
这道题大家一拿上就会想到模拟。
那么我们用模拟做一下。
#include<bits/stdc++.h> //我总算掌握万能头文件了
using namespace std;
int main()
{int n,i,j,o[105],l[105],t[105],flag=0,sum=0,u[105]; //定义所需数组 cin>>n; for(i=1;i<=n;i++) //初始化数组 {o[i]=i;t[i]=i;u[i]=i;}for(i=1;i<=n;i++) //输入变化规律 {cin>>l[i];}while(1) //不知道什么时候结束就用这个 {for(i=1;i<=n;i++) //变化 {o[l[i]]=t[i];}sum++; //记录变化次数 flag=0; //用于标记是否与原数组相等 for(i=1;i<=n;i++){if(o[i]!=u[i]) //如果与原数组不相等 { flag++; //标记 }}if(flag==0) //没有标记就是与原数组相等 {cout<<sum;exit(0); //强力结束! }for(i=1;i<=n;i++) //及时更新 {t[i]=o[i];}}
}
当你看到样例过了兴冲冲的提交才发现——————
这么写只能得30分!
(此时的精神状态)
这道题的满分做法是找环再求最小公倍数。
我们仔细观察一下。
我们可以发现:1,2成一个环,3,4,5成一个环。
然后我们把几个环的长度求最小公倍数即可。
#include<bits/stdc++.h> //万能头用上瘾
using namespace std;
int a[100005],o[1000005],w,sum,flag[1000005],b[100005],cnt,gbsh,gys; //好多啊
int main()
{int i,sum=0,n,j; //这还有几个 cin>>n; for(i=1;i<=n;i++) //输入 {cin>>a[i];}for(i=1;i<=n;i++) //核心 {if(flag[i]==0) //如果没有标记 说明还没有成环 {w=i; //w记录当前位置 sum=1; //第一个位置也算所以初始值是1 flag[w]=1; //当前位置必须标记! while(1) //熟悉配方 {if(flag[a[w]]==0) //如果下一个位置没有标记 {sum++; //环的长度 flag[a[w]]=1; //下一个位置必须标记! }else{break; //已经有环了跳过 }w=a[w]; //当前位置更新! }cnt++; //环的个数 b[cnt]=sum; //记录环的长度 }}//求最小公倍数 for(i=1;i<cnt;i++) //有可能会超出所以是 <cnt {//先求最大公因数 for(j=max(b[i],b[i+1]);j>=1;j--){if(b[i]%j==0&&b[i+1]%j==0){gys=j;}}gbsh=b[i]*b[i+1]/gys; //求A与B的最小公倍数方法:A*B÷C (C表示两数的最大公因数) }cout<<gbsh<<endl; //这才是最终答案return 0; //潇洒结束
}
求最大公因数和最小公倍数有种算法叫欧几里得算法,等到学了一定会给大家及时更新!
感谢阅览!欢迎一键三连!欢迎订阅专栏!Thanks♪(・ω・)ノ