毫无卵用的百度百科

Definition&Solution

  对于一个给定的链表,如何判定它是否存在环以及环的长度问题,可以使用Floyd消圈算法求出。

  从某种意义上来讲,带环的链表在本质上是一个有向图

  考虑下面的事实:假定小Y和小Z在圆形操场上跑步,小Z的速度是小Y的两倍,那么总存在一个时刻,使得小Z和小Y在同一个位置但是小Z比小Y多跑了若干圈。

  该算法的复杂度为O(n)。

  代码如下:

void floyd_c() {
int c1=list_begin,c2=list_begin;//c=child
do {
c1=nxt[c1];
c2=nxt[c2]; dosth();
c2=nxt[c2]; dosth();
} while(c1!=c2);
return;
}

  其中dosth应具体情况具体分析。

  考虑如何求出该环的起点。

  如果你不理解环为什么有起点,不妨观察下面的链表:

  由于1是链表的起点,以1号点为起点遍历整张链表,是从3号点进入原谅环的,我们认为3号点是原谅环的起点。

  如何求出起点。

  将小Z和小Y都放到链表的起点上,当两者相遇时,将其中一个指针再次放到起点上,二者再次相遇的位置就是环的起点。

  证明如下:

    由于含有多个环的链表可以通过数学归纳由含有一个环的链表证明,故不妨设所研究的链表只有一个环,同时还有一条长度至少为1(一个点)的链。

    设环的长度为n,链的长度为m。快慢指针第一次相遇在环上的第k个点,那么有:

    快指针的路程Sa=m+A*n+k,其中A∈Z,代表走了几圈①

    慢指针的路程Sb=m+B*n+k。其中B∈Z,代表走了几圈②

    由于快指针的速度是慢指针的两倍,即:

    Va=2Vb③

    在运动时间一定的情况下有:

    Sa=2Sb④

    ①-②得:

    Sa-Sb=(A-B)*n⑤

    联立④⑤解得Sb=(A-B)*n⑥

    由于A,B∈Z,且显然A>B,所以Sa,Sb都是圈长度的倍数。

    不妨设Sb=T*n。显然从起点出发,走过T*n+m时,到达环的起点。

    那么在两个指针相遇时,我们让两个指针的速度都为1,走m个单位就可以到达环的起点,这时快指针的路程为2Sb+m。慢指针的路程为Sb+m。

    由于Sb=T*n,这时的路程可以理解为快指针走到m处然后绕了几圈,绕圈路程为2Sb,慢指针从路程为Sb的位置走了m,那么二者的相遇的地方显然是环的起点。

    特别的,因为vb=1。所以Sb即为循环的次数。通过⑥式已经证明,该算法的复杂度为O(n)。其中常数随环的形态而改变。

 

Sample

UVA11549 Calculator Conundrum

Description

有一个非常无聊的傻逼,有一天他闲的没事干玩一个老式计算器,这个计算器只能显示答案最高的n位。比如n=2,计算99+1的答案为100时,显示为10。

现在他一开始输入了一个数字k,保证在能显示的范围内,然后将k平方,然后将答案平方,再平方……

这个无聊的人想知道屏幕上显示的最大数时多少。

Input

第一行是数据组数,对于每组数据,包含:

  • 一个整数n,一个整数k

Output

对于每组数据,输出:

  • 对应答案

Sample Input


Sample Output


Hint

n≤9

Solution

简单的数学归纳可以证明计算器上的数字是会出现循环的,可以使用Floyd消圈算法解决此题。

Code

#include<cstdio>
#define rg register
#define ci const int
#define ll long long int inline void qr(int &x) {
char ch=getchar(),lst=NULL;
while(ch>''||ch<'') lst=ch,ch=getchar();
while(ch>=''&&ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
if (lst=='-') x=-x;
} char buf[];
inline void write(int x,const char aft,const bool pt) {
if(x<) {putchar('-');x=-x;}
int top=;
do {
buf[++top]=x%+'';
x/=;
} while(x);
while(top) putchar(buf[top--]);
if(pt) putchar(aft);
} template <typename T>
inline T mmax(const T &a,const T &b) {if(a>b) return a;return b;}
template <typename T>
inline T mmin(const T &a,const T &b) {if(a<b) return a;return b;}
template <typename T>
inline T mabs(const T &a) {if(a<) return -a;return a;} template <typename T>
inline void mswap(T &a,T &b) {T temp=a;a=b;b=temp;} int t,n,k,ans; int nxt(ci); int main() {
qr(t);
while(t--) {
n=k=;qr(n);qr(k);
int c1=k,c2=k;ans=k;
do {
c1=nxt(c1);
c2=nxt(c2);ans=mmax(ans,c2);c2=nxt(c2);ans=mmax(ans,c2);
} while(c1!=c2);
write(ans,'\n',true);
}
return ;
} short bufff[];
int nxt(int x)
{
if(!x)return ;
long long kf=(long long)x*x;
int L=;
while(kf>) bufff[L++]=kf%,kf/=;
int temp=n;
if(temp>L) temp=L;
int sum=;
for(int i=;i<temp;++i) sum=(sum<<)+(sum<<)+bufff[--L];
return sum;
}

Summary

  1、Floyd消圈算法是达到理论下限的判断有向图上环的算法。尽管它的常数难以控制,但是十分的实用并且好写。

  2、在证明的最后使用了等效替代法,在其他的OI毒瘤题中,也应注意该方法的应用。

【图论】Floyd消圈算法的更多相关文章

  1. SGU 455 Sequence analysis(Cycle detection,floyd判圈算法)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=455 Due to the slow 'mod' and 'div' operati ...

  2. UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈算法)

    CALCULATOR CONUNDRUM   Alice got a hold of an old calculator that can display n digits. She was bore ...

  3. UVA 11549 Calculator Conundrum (Floyd判圈算法)

    题意:有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 思路:这个题一定会出现 ...

  4. leetcode202(Floyd判圈算法(龟兔赛跑算法))

    Write an algorithm to determine if a number is "happy". 写出一个算法确定一个数是不是快乐数. A happy number ...

  5. Floyd判圈算法

    Floyd判圈算法 leetcode 上 编号为202 的happy number 问题,有点意思.happy number 的定义为: A happy number is a number defi ...

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

    一句话题意:x0=1,xi+1=(Axi+xi%B)%C,如果x序列中存在最早的两个相同的元素,输出第二次出现的位置,若在2e7内无解则输出-1. 题解:都不到100天就AFO了才来学这floyd判圈 ...

  7. Floyd判圈算法 UVA 11549 - Calculator Conundrum

    题意:给定一个数k,每次计算k的平方,然后截取最高的n位,然后不断重复这两个步骤,问这样可以得到的最大的数是多少? Floyd判圈算法:这个算法用在循环问题中,例如这个题目中,在不断重复中,一定有一个 ...

  8. Floyd 判圈算法

    Floyd 判圈算法 摘自维基百科, LeetCode 上 141题 Linked List Cycle 用到这个, 觉得很有意思. 记录一下. 链接: https://zh.wikipedia.or ...

  9. UVa 11549 计算器谜题(Floyd判圈算法)

    https://vjudge.net/problem/UVA-11549 题意: 有一个老式计算器,只能显示n位数字,输入一个整数k,然后反复平方,如果溢出的话,计算器会显示结果的最高n位.如果一直这 ...

随机推荐

  1. requests,lxml爬启信宝

    首先, 添加requests模块: 然后, 添加lxml模块: 启信宝登录抓包: QiXinBao.py: import requestsfrom lxml import etree loginUrl ...

  2. JMeter常用元器件

    测试计划, 是整个工程的根节点, 可以取别名, 并添加注释, 里面的设置是全局变量: 线程组, 是一组线程的集合, 可以取别名, 并添加注释, 里面的设置只对本线程组有效: HTTP请求, 也就是取样 ...

  3. 使用httpClient获取请求cookie

    package mytest; import java.util.ArrayList; import java.util.List; import org.apache.http.NameValueP ...

  4. 181. Flip Bits【LintCode, by java】

    Description Determine the number of bits required to flip if you want to convert integer n to intege ...

  5. 【第二章】Shell 变量

    一.什么是变量? 变量就是一个固定的字符串(也可以是字符.数字的组合)代替更多.更复杂的内容,该内容可能是变量.路径.字符串等其他内容. 变量就是程序中保存用户数据的一块内存空间,而变量名就是这块内存 ...

  6. ZOJ 2532 Internship(最大流找关键割边)

    Description CIA headquarter collects data from across the country through its classified network. Th ...

  7. 第一章 Windows编程基础(1~4课)

    第一课:从main到WinMain 第二课:窗口和消息 第三课:MFC编程 第四课:MFC应用程序框架 概括: Win32的两种编程框架:SDK方式.MFC方式 1. SDK方式:使用WinMain入 ...

  8. “Hello World!”团队——Alpha发布用户使用报告

    博客内容: 1.用户体验报告表 2.用户评论截图 3.总结 一.用户体验报告表 用户使用报告 用户序号 用户姓名(化名) 性别 用户职业 使用频次 用户评论 1 小董 女 文学在读硕士 5 1.游戏界 ...

  9. Thunder团队Beta周贡献分分配结果

    小组名称:Thunder 项目名称:爱阅app 组长:王航 成员:李传康.翟宇豪.邹双黛.苗威.宋雨.胡佑蓉.杨梓瑞 分配规则 规则1:基础分,拿出总分的20%(8分)进行均分,剩下的80%(32分) ...

  10. 由作业题引发对C++引用的一些思考

    首先分析一段代码: #include <bits/c++config.h> #include <ostream> #include <iostream> #incl ...