Codeforces Gym 101252D&&floyd判圈算法学习笔记

一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1。

题解:都不到100天就AFO了才来学这floyd判圈算法。

介绍一下floyd判圈算法:该算法适用于在线性时间复杂度内判断有限自动机、迭代函数、链表中是否有环,求环的起点(即链长)和环长。

Codeforces Gym 101252D&&floyd判圈算法学习笔记

可以先这么做:首先从起点S出发,给定两个指针,一个快指针一个慢指针,然后每次快指针走1步,慢指针走2步,直到相遇为止。如果已经到达终点/达到规定步数时仍然没有相遇,说明图中没有符合条件的环。如果相遇了,可以确定进入了环(如图则在M点相遇),接下来就要计算环长和环起点。

计算环长:令其中一个指针一直走下去,记录步数即可,因为其在环内,最终一定会在线性复杂度内再次返回节点M。

计算环起点:令其中一个指针位于M,另一个回到S,然后两者以相同速度推进,相遇的点就是环的起点。

证明:留坑,后序补上。

Codeforces Gym 101252D:显然是一道裸题,上code

Codeforces Gym 101252D&&floyd判圈算法学习笔记
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e7;
ll a,b,c,s,r,x,y; 
int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    cin>>a>>b>>c;
    x=y=1;
    while(s<N)
    {
        s++;
        y=(a*y+y%b)%c,y=(a*y+y%b)%c;
        x=(a*x+x%b)%c;
        if(x==y)break;
    }
    if(x!=y){puts("-1");return 0;}
    while(r<N)
    {
        r++;
        y=(a*y+y%b)%c;
        if(x==y)break;
    }
    if(x!=y){puts("-1");return 0;}
    s=0,y=1;
    while(x!=y&&s<N)
    {
        s++;
        y=(a*y+y%b)%c;
        x=(a*x+x%b)%c;
    }
    s+=r;
    if(x==y&&s<=N)cout<<s;
    else puts("-1");
    return 0;
}
View Code

 

上一篇:多源最短路算法——Floyd算法


下一篇:(传输层)UDP协议