前天晚上去acdream群赛找虐,看到一道斐波那契数列的题,就是要求循环节
第一反应是想到博客里某个人发的一篇 Fib数模n的循环节 ,想都没想直接拷过来交了一发,Wa了,看不懂的代码还是懒得改,于是放弃了
第二反应是想到了 Fibonacci Returns 这个题是求 Fib(C(n,r))%p ,代码可以看这里,也是要求循环节,然后把整个代码拷过来,改了改,交了一发超时了
呵呵,尼玛,感觉这半年差不多废了,啥都不会了
然后在解题报告里,学到了新姿势:解题报告
那么,以群赛里的这个题为模版吧:
Problem: 喵喵的遗憾
Code: acdream1124.cpp
然后觉得有必要改一下之前做过的一个题的姿势
Problem: A Short problem
之前的做法是暴力递推式,找循环节,由于取模数已经固定了,暴出来后就不需要重新计算,所以时限很好搞定,万一取模数是输入的呢,原来的办法就跪了吧
开始的时候有点sb,直接只改了矩阵的部分,发现循环节求出来loop(1000000007)=222222224,loop(222222224)=36624!=183120,难道是模版有问题?但是我看了思路没问题啊,郁闷了好久
今天早上起来后,看了下代码,为什么要判断5是不是p的模二次剩余呢,为什么是5呢
想了想,5对于斐波那契数列来讲,不就是x^2=x+1的delta么,那么这题的递推式是x^2=3*x+1,delta=3*3+4=13,然后我就把勒让德符号判断二次剩余那里改成13,然后对应的暴力出13及13以内的素数对应的循环节,交了一发,AC了
Code:hdu4291.cpp
Problem: Evil teacher's Final Problem
同样是斐波那契数列的循环节,只不过递归的层数可能有1w,没有什么技巧,多加了个map存求过的答案
Code: hdu3978.cpp
当然从一开始,我们要解决的是斐波那契循环节的问题,但是我们发散思维想一想,是不是可以求一系列矩阵快速幂中的类似问题,像那个g(n)=3*g(n-1)+g(n-2)的问题,诸如此类的递推式的循环节都可以这样求了吧
大致说下递推式循环节的解决方案:
problem: f(n)=a*f(n-1)+b*f(n-2),求f(n)%p的循环节
solution:
1.对p进行质因数分解,p = p1^a1 * p2^a2 * p3^a3 ... * pn^an
2.分别求 p1^a1,p2^a2,...,pn^an的循环节,然后取最小公倍数
至于怎么求对 px^ax 的循环节,这里用到了二次剩余
2.1 p mod px^ax 的循环节 = G(px) * px^(ax-1) , G(px) 就是 p mod px 的最小循环节
2.2 对于递推式,我们可以得到特征根方程 x^2=a*x+b ,delta=a*a+4*b
2.3 对于G(px),如果delta是模px的二次剩余,G(px)是px-1的因子,否则G(px)是(px-1)*(px+1)的因子
暴力找到最小的就可以了
Problem: 神奇的%系列三
Code: acdream1075.cpp