毫无卵用的百度百科

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. 接口测试工具postman(六)添加变量(参数化)

    1.添加全局变量并引用 2.通过设置请求前置配置变量 3.在Tests里面,把响应数据设置为变量 4.添加外部文件,引用外部文件中的变量和数据,此种场景就可以执行多次请求 1)配置文件,txt或者cs ...

  2. ant-design学习准备_1

    在学习ant-desin过程中,发现很多知识都不清楚,从现在开始,每天将自己学习到的知识进行一个总结记录,前端大佬勿扰勿喷.先介绍几个基础概念和一些常用命令: 1.什么是脚手架 我们经常在各个博客论坛 ...

  3. Windows10安装GPU版本的Tensorflow

    本人电脑配置(公司的)gtx1080ti,下载的的cuda8.0,cudnn6.0,python3.5.3安装完成后,安装tensorflow 1.pip install tensorflow-gpu ...

  4. Dask教程

    Dask 介绍 Dask是一款用于分析计算的灵活并行计算库. Dask由两部分组成: 针对计算优化的动态任务调度.这与Airflow,Luigi,Celery或Make类似,但针对交互式计算工作负载进 ...

  5. 机器学习(四)正则化与过拟合问题 Regularization / The Problem of Overfitting

    文章内容均来自斯坦福大学的Andrew Ng教授讲解的Machine Learning课程,本文是针对该课程的个人学习笔记,如有疏漏,请以原课程所讲述内容为准.感谢博主Rachel Zhang 的个人 ...

  6. 提升方法-AdaBoost

    提升方法通过改变训练样本的权重,学习多个分类器(弱分类器/基分类器)并将这些分类器进行线性组合,提高分类的性能. AdaBoost算法的特点是不改变所给的训练数据,而不断改变训练数据权值的分布,使得训 ...

  7. truffle框架快速开发合约步骤

    矩阵元区块链智能合约开发指南 1 适用范围 本规范描述了矩阵元区块链系统智能合约的开发约束与规范,用以指导DAPP开发者按照本规范开发基于矩阵元区块链运行的应用. 2 术语解释 术语 术语解释 DAP ...

  8. Objective-C 反射机制

    该文章属于<简书 — 刘小壮>原创,特此感谢:<简书 — 刘小壮> http://www.jianshu.com/p/5bbde2480680 了解反射机制 Objective ...

  9. Thinkphp5的ajax接口实现

    前一篇讲到thinkphp5从数据库获取数据之后赋给视图view,前一篇从数据渲染方式来说是服务端数据渲染,这一章则是浏览器端数据渲染.按照知识总结依据来划分,这是两种不同的技术场景. 下面介绍具体的 ...

  10. windows批处理学习---01

    一. 标记符号: CR(0D) 命令行结束符 Escape(1B) ANSI转义字符引导符 Space() 常用的参数界定符 Tab() ; = 不常用的参数界定符 + COPY命令文件连接符 * ? ...