Floyed判环/龟兔算法
求[(5+2√6)2^x+1 ] mod p 的值,其中 0 ≤ x < 232 , p 是个质数,p ≤ 46337 .(这里介绍的是一种暴力的做法)
(5+2√6)2^n+1 = an + bn·√6 ----©,
(5-2√6)2^n+1 = an - bn·√6 ;
所以(5+2√6)2^n+1 + (5-2√6)2^n+1 = 2an ;
因为5-2√6<1 , 所以[(5+2√6)2^x+1 ] = 2an - 1 ;
然后(5+2√6)2^x+1 = (5+2√6) ·(an-1 + bn-1·√6) -----®;
由C,R得:
an=5an-1 + 12bn-1 ,
bn=2an-1 + 5bn-1 ;
所以我们要求的就是 a2^x+1 ;
但是即使用矩阵快速幂,复杂度为O(x) , 所以并卵 ; 同时矩阵并不能用 欧拉定理 进行优化。
所以 波老师 就大胆的猜测对于这个问题 an mod p 的 循环节不会很大 , 所以之后就是暴力找循环节了。
- floyed判圈算法描述:
我们令周期为λ,非周期的长度大小为μ,
他能在O(λ+μ)的时间复杂度 ,O(1)的空间复杂度内,得到λ ,μ 。
- 试用范围:
functional graph:每个点只有一个出度的有向图。
形象的一点说明如果 an = f (an-1) ,那么你就可以对这个数列用floyed判圈。
(对于这道题就是 an = F (an-1 , bn-1) , bn = G (an-1 , bn-1) , 所以自然适用。)
再比如 链表 ……
- 描述及证明:
我们设od为数列的初始状态,Next()为让an-1推出an的递推函数,和两个变量 turt , hare ,相遇点为 x , 进环点为 o。
首先我们令 turt = hare = od ;
然后我们令turt , hare开始移动 : turt 没回合移动一个点 , 表示为 turt = Next (turt) ; hare 每回合移动两个点,表示为 hare = Next ( Next (hare)) ;
如果画成图的话,你可以形象的认为,turt每回合只走一步,hare没回和走两步。
然后我们可以得到两个结论:
- 如果Next () graph 没有环,那么在任何时刻 turt != hare ,并且两者是充要的。
- 如果Next () graph 有环 , 那么必然会有 turt == hare 的时候 , 让我来证明一下:

hare跑啊跑啊,进到圈里了,但是他永远跑不出去了;turt跑啊~跑啊~ ,终于进圈了,它往逆时针的方向瞟了一眼,发现hare在他后面 y 个节点上,turt 心算了一下 再过 y / (2 - 1)的时间hare才追上自己,turt就开心的笑了。
我们对 x 时的状态分析一下:
turt : i = μ + a·λ + x ;
hare : 2·i = μ + b·λ + x ;
所以turt 到这一点所走的路程 i = (b - a)·λ -----À
让我们继续分析下去,在 x 处turt , hare相遇了,我们可以认为在这时他们的路程差为 λ ,所以下一次相遇的时间为 λ / (2-1) = λ , 所以我们又可以得到两个结论:
1.如果我们模拟turt , hare的下一次相遇,那么 turt 所走的路程 1·λ = λ , 所以周期求得。
2.由1可知,两者相遇点仍旧是 x 。
最后只剩下 μ 了:
由À可知如果turt再往前走 μ 步,turt必然会回到 o 点 ,证明:i + μ Ξ μ (mod p) , 又因为从 od 走到 o 点需要 μ 步, 所以得证。
那么又要怎么实现呢?我们令 turt 保持在 x 时的状态 , 让hare = od ;
接下来让 turt , hare 以每回合都以 turt = Next(turt) , hare = Next (hare) 运动,那么他们又会相遇了,这一次显然是在o点相遇,记录这个走的步数及得到 μ 。
伪代码:
void Floyed () {
pii hare = od , turt = od;
lam = mu = 0 ;
int cnt = 0 ;
while(1) {
hare = Next (Next (hare) ) ;
turt = Next ( turt) ;
if (hare.F == turt.F && hare.S == turt.S) break ;
}
while (1) {
hare = Next (Next (hare) ) ;
turt = Next (turt) ;
lam ++ ;
if (hare.F == turt.F && hare.S == turt.S) break ;
}
hare = od ;
while (1) {
hare = Next (hare) ;
turt = Next (turt) ;
if (hare.F == turt.F && hare.S == turt.S) break ;
mu ++ ;
}
printf ("mu = %d , lam = %d\n" , mu , lam) ;
}
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5451
关于这道题目的后记:
正解其实利用了 广义fib找循环节 的一个性质:http://blog.csdn.net/ACdreamers/article/details/25616461
然后直接对(5+2√6)2^n+1 + (5-2√6)2^n+1用了二阶常系数线性递推,然后用伟达定理得到了an = 10·an-1 - an-2 ;









但是这种东西我不会,后来就想能不能用
an=q·an-1 + p·bn-1 ,
bn=s·an-1 + t·bn-1 ;
推出an , an-1 , an-2 的关系式呢?
然后真的找到了:an = (q+t) · an-1 + (p·s - q·t) · an-2 ;
证明:
p · bn - t · an = (ps - qt) · an-1 ;
p · bn = (ps - qt) · an-1 + t · an ;
所以:p · bn-1 = (ps - qt) · an-2 + t · an-1 ;
带回 an=q·an-1 + p·bn-1 ;
得证 an = (q+t) · an-1 + (p·s - q·t) · an-2 ;
Floyed判环/龟兔算法的更多相关文章
- 【set&&sstream||floyed判环算法】【UVa 11549】Calculator Conundrum
CALCULATOR CONUNDRUM Alice got a hold of an old calculator that can display n digits. She was bored ...
- 龟兔赛跑算法 floyed判环算法
今天写线段树写到要用到这个算法的题目,简单的学习一下. https://blog.csdn.net/javaisnotgood/article/details/89243876 https://blo ...
- Floyd 循环检测算法(快慢指针法/龟兔指针法)
Floyd Cycle Detection Algorithm Floyd Cycle Detection Algorithm,即 Floyd 循环检测算法,又称快慢指针法.龟兔指针法.该算法用于 ...
- floyd判环算法(龟兔赛跑算法)
floyd判环算法(龟兔赛跑算法) 注意,这个算法是用来判断一条链+一条环的图,环的长度或者环与链的交界处的,所以此floyd非彼floyd(虽然都是一个人想出来的). (图不是我的) 如果只要求环的 ...
- hdu4975 A simple Gaussian elimination problem.(正确解法 最大流+删边判环)(Updated 2014-10-16)
这题标程是错的,网上很多题解也是错的. http://acm.hdu.edu.cn/showproblem.php?pid=4975 2014 Multi-University Training Co ...
- hdu4888 Redraw Beautiful Drawings 最大流+判环
hdu4888 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/6553 ...
- CodeForces 937D 936B Sleepy Game 有向图判环,拆点,DFS
题意: 一种游戏,2个人轮流控制棋子在一块有向图上移动,每次移动一条边,不能移动的人为输,无限循环则为平局,棋子初始位置为$S$ 现在有一个人可以同时控制两个玩家,问是否能使得第一个人必胜,并输出一个 ...
- Leetcode 166. Fraction to Recurring Decimal 弗洛伊德判环
分数转小数,要求输出循环小数 如2 3 输出0.(6) 弗洛伊德判环的原理是在一个圈里,如果一个人的速度是另一个人的两倍,那个人就能追上另一个人.代码中one就是速度1的人,而two就是速度为2的人. ...
- Leetcode 202 Happy Number 弗洛伊德判环解循环
今天先谈下弗洛伊德判环,弗洛伊德判环原来是在一个圈内有两人跑步,同时起跑,一人的速度是另一人的两倍,则那个人能在下一圈追上另一个人,弗洛伊德判环能解数字会循环出现的题,比如说判断一个链表是不是循环链表 ...
随机推荐
- Java中的static关键字解析
Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...
- 环境变量NLS_LANG
NLS_LANG是一个环境变量,用于定义语言,地域以及字符集属性.对于非英语的字符集,NLS_LANG的设置就非常重要.NLS:‘National Language Support (NLS)’ 当我 ...
- JS中变量名和函数名重名
今天骚凯问了一道变量名冲突的题目,感觉很有意思,顺便也复习一下预解析的一些知识,有不对的地方忘前辈大神指正,题目是这样的: var a=100; function a(){ console.log(a ...
- webconfig中配置各种数据库的连接字符串(转)
一.在appSettings配置 <appSettings> <!--SQL Server--> <!--<add key="SQLString&qu ...
- css设置select高度(IE,FF,Chrome)[转]
大家都知道select是无法设置高度和边框颜色等等的在ie67下面,其他的都是可以的,所以有时候为了在所有的浏览器下显示都一致,就使用了 js的模拟,这个是大家经常碰到的,js不光要模拟外观还有模拟事 ...
- 深入理解Java:注解
注解作用:每当你创建描述符性质的类或者接口时,一旦其中包含重复性的工作,就可以考虑使用注解来简化与自动化该过程. Java提供了四种元注解,专门负责新注解的创建工作. 元注解 元注解的作用就是负责注解 ...
- WPF MVVM 验证
WPF MVVM(Caliburn.Micro) 数据验证 书接前文 前文中仅是WPF验证中的一种,我们暂且称之为View端的验证(因为其验证规是写在Xaml文件中的). 还有一种我们称之为Model ...
- 点击按钮后到底发生了什么,Touch,LongClick或者Click?
按钮点击事件详解 最近一个项目需要给应用初始界面上的动态按钮添加在不同状态的变换效果,如点击(俗一点也可称为按压)后实现背景图的更换或者图标的缩放等效果.由于按钮点击的时间有长有短,所以采用OnTou ...
- JQuery中Ajax的操作
JQuery Ajax异步操作的方式: $.ajax,$.post, $.get, $.getJSON. 一, $.ajax,这个是JQuery对ajax封装的最基础步,通过使用这个函数可以完成异 ...
- MongoDB基础知识
一.Mongodb简介 Mongodb是基于分布式文件存储的数据库,用C++编写: Mongodb是nosql(not-only-sql)数据库: Mongodb '无状态模式',不用去设计,直接用, ...