AtCoder Beginner Contest 167 比赛人数11940 比赛开始后15分钟看到A题,之后每隔一分钟,看到一道题,在比赛开始后第21分钟看到所有题
AtCoder Beginner Contest 167 D Teleporter 找周期
总目录详见https://blog.csdn.net/mrcrack/article/details/104454762
在线测评地址https://atcoder.jp/contests/abc167/tasks/abc167_d
在离比赛结束前,不到3分钟时,第一发WA.在离比赛结束前5s,第二发,按下提交按钮的同时,比赛也弹出对话框说,结束,一看结果,在21:40到达前,竟然提交成功了,21:40之后看了看,AC了,这种情况比赛算成绩吗,不断的刷新网站,22:04才发现,比赛承认这次提交的成绩。不得不说,最后阶段,提交的灵敏度,AtCoder强于CodeForces.
真是佩服自己有颗强大的心脏。用了25分钟,从读题开始,中间WA了一次,到AC.
样例1
1->3->4->1周期是3
5%3=2,这2次这样走1->3->4,故最后位置是4
样例2
1->6->2->5->3->2
2->5->3->2周期是3
请注意,之前还多了一段1->6->2,这段次数是2
首先扣除次数是2的多余段727202214173249351-2=727202214173249349
727202214173249349%3=0很明显,回到周期的起始位置2
AC代码如下
#include <stdio.h>
#define LL long long
#define maxn 200010
LL k,t;
int n,a[maxn],vis[maxn];
int main(){
int i,nx,s,b,c;
scanf("%d%lld",&n,&k);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
nx=1;//请注意,从位置1开始
while(1){
vis[nx]=1,nx=a[nx];
if(vis[nx]){s=nx;break;}//寻找周期的起始位置s
}
nx=s;//请注意,从位置s开始
for(i=1;i<=n;i++)vis[i]=0;
while(1){
vis[nx]=1,nx=a[nx],t++;//计算周期长度t
if(vis[nx])break;
}
b=0,nx=1;//请注意,从位置1开始
while(1){
if(nx==s)break;
nx=a[nx],b++;//计算周期正式开始前,多出的次数b
}
c=0;
if(k<=b){//k值较小,还没有正式开始周期
nx=1;
while(1){
if(k==c)break;
nx=a[nx],c++;
}
printf("%d\n",nx);
return 0;
}
k-=b;k%=t;//k值较大,先扣除周期正式开始前,多出的次数b
{
nx=s;//请注意,从位置s开始
c=0;
while(1){
if(k==c)break;
nx=a[nx],c++;
}
printf("%d\n",nx);
}
}