AtCoder Beginner Contest 167 D Teleporter 找周期

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 
#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);
	}
}

 

你可能感兴趣的:(atcoder)