很容易看出来这道题是求模n意义下fib数列的最小循环节

对于fib数列的最小循环节的求法,我们可以这样:

1、令n=p1^m1 * p2^m2 * p3^m3……

2、分别计算fib数列在模p1^m1,p2^m2……意义下的最小循环节

3、模n意义下的最小循环节为2步骤各循环节的LCM

首先步骤三是非常容易证明的,CRT直接可以看出来

我们考虑如何计算p1^m1的循环节

这里有一个定理:G(p1^m1)=G(p1)*p1^(m-1)

我们只需要计算G(p)就可以了

我们知道对于Fib数列,满足f(i)=1.0/sqrt(5) *( (1+sqrt(5))/2)^i - ((1-sqrt(5))/2)^i)

那么在模p意义下存在以下两种情况:

1、5是模p意义下的二次剩余,即满足欧拉判别 5^((p-1)/2)=1

那么原式中的sqrt(5)在模意义下可以用整数x替代

由费马小定理很容易知道F(p-1)=0

又知道

((1+x)/2)^p=(1+x)/2

((1-x)/2)^p=(1-x)/2

两式做差等于x

所以F(p)=1

因此我们知道p-1是Fib数列的一个循环节,那么其最小循环节一定是p-1的约数

枚举+矩阵乘法判断即可

2、5不是模p意义下的二次剩余,则存在5^((p-1)/2)=-1

那么由二项式定理得

(1+sqrt(5))^p=1+(sqrt(5))^p

(1-sqrt(5))^p=1-(sqrt(5))^p

(因为其系数的组合数里含有p这个因子的时候值为0)

两式做差得2*sqrt(5)^p

进而得F(p)=(sqrt(5)/2)^(p-1)

我们知道在模p意义下2^(p-1)的逆元为1

所以F(p)=(sqrt(5))^(p-1)=5^((p-1)/2)=-1

同理,我们可以得到F(p+1)=0

设Fib数列在模意义下第一个F(i)=0且i不等于0的位置为i

设F(i-1)=a 易证(a,p)=1

则一定有i是p+1的约数

且F(p)=a^j*F(p-i*j)

显然F(p-i*j)=a,所以F(p)=a^(j+1)

进而知道F(2*p+1)=a^(2*j+2)=(-1)^2=1

F(2*p+2)=0

所以2*(p+1)是Fib数列的一个循环节,那么其最小循环节一定是2*(p+1)的约数

枚举+矩阵乘法判断即可

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std; const int maxn=20010;
typedef long long LL;
LL n,mod,now;
LL a,b,ans;
LL st[maxn],top=0;
struct Matrix{
LL a[2][2];
void clear(){memset(a,0,sizeof(a));}
void print(){
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
printf("%lld ",a[i][j]);
}printf("\n");
}printf("\n");
}
}A;
LL mul(LL a,LL b){
LL s=0;
while(b){
if(b&1)s=(s+a)%mod;
a=(a<<1)%mod;b>>=1;
}return s;
}
LL GCD(LL a,LL b){return b==0?a:GCD(b,a%b);}
LL LCM(LL a,LL b){return a*b/GCD(a,b);}
LL Get_pow(LL v,LL p){
LL tmp=1;
while(p){
if(p&1)tmp=mul(tmp,v);
v=mul(v,v);p>>=1;
}return tmp;
}
Matrix operator *(const Matrix &A,const Matrix &B){
Matrix C;C.clear();
for(int i=0;i<2;++i){
for(int j=0;j<2;++j){
for(int k=0;k<2;++k){
C.a[i][j]=C.a[i][j]+mul(A.a[i][k],B.a[k][j]);
if(C.a[i][j]>=mod)C.a[i][j]-=mod;
}
}
}return C;
}
Matrix pow_mod(Matrix v,LL p){
Matrix tmp;tmp.clear();
tmp.a[0][0]=tmp.a[1][1]=1;
while(p){
if(p&1)tmp=tmp*v;
v=v*v;p>>=1;
}return tmp;
}
void F(LL p){
A.a[0][0]=1;A.a[0][1]=1;
A.a[1][0]=1;A.a[1][1]=0;
A=pow_mod(A,p-1);
b=(A.a[0][0]+A.a[0][1])%mod;
a=(A.a[1][0]+A.a[1][1])%mod;
}
LL Get_loop(LL k){
if(k==2)return 3;
else if(k==3)return 8;
else if(k==5)return 20;
LL p;mod=k;top=0;
if(Get_pow(5LL,(mod-1)>>1)==1)p=mod-1;
else p=2*(mod+1);
for(LL i=1;i*i<=p;++i){
if(p%i==0){
LL x=i,y=p/i;
F(x);
if(a==0&&b==1)return x;
if(y!=x)st[++top]=y;
}
}
while(top){
F(st[top]);
if(a==0&&b==1)return st[top];
top--;
}return 0;
} int main(){
while(scanf("%lld",&n)==1){
now=n;ans=1;
for(LL i=2;i*i<=now;++i){
if(now%i==0){
LL S=1;
while(now%i==0)now/=i,S*=i;
S/=i;S=S*Get_loop(i);
ans=LCM(ans,S);
}
}
if(now>1){
LL S=Get_loop(now);
ans=LCM(ans,S);
}
if(ans%2==0)ans/=2;
printf("%lld\n",ans);
}return 0;
}

  

hdu 4794 FIb求循环节的更多相关文章

  1. Cyclic Nacklace - HDU 3746(next求循环节)

    题目大意:给你一些串,问如果想让这个串里面的循环节至少循环两次,需要添加几个字符(只能在最前面或者最后面添加).比如ababc 需要添加5个就是添加ababc. 分析:其实字符串的长度len-next ...

  2. hdu 3746 kmp求循环节

    题意就是将所给的字符串变成多个完整的循环(至少两个),然后给出最少需要添加的字符数.

  3. hdu 4291(矩阵+暴力求循环节)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4291 思路:首先保留求出循环节,然后就是矩阵求幂了. #include<iostream> ...

  4. hdu 3374 String Problem (字符串最小最大表示 + KMP求循环节)

    Problem - 3374   KMP求循环节. http://www.cnblogs.com/wuyiqi/archive/2012/01/06/2314078.html   循环节推导的证明相当 ...

  5. hdu 4291 矩阵幂 循环节

    http://acm.hdu.edu.cn/showproblem.php?pid=4291 凡是取模的都有循环节-----常数有,矩阵也有,并且矩阵的更奇妙: g(g(g(n))) mod 109  ...

  6. 区间DP+next求循环节 uva 6876

    // 区间DP+next求循环节 uva 6876 // 题意:化简字符串 并表示出来 // 思路:dp[i][j]表示 i到j的最小长度 // 分成两部分 再求一个循环节 #include < ...

  7. HDU 4259 - Double Dealing(求循环节)

    首先将扑克牌进行一次置换,然后分解出所有的循环节,所有循环节的扑克牌个数的最小公倍数即为答案 #include <stdio.h> #include <string.h> #i ...

  8. 51nod 1126 求递推序列的第N项 思路:递推模拟,求循环节。详细注释

    题目: 看起来比较难,范围10^9 O(n)都过不了,但是仅仅是看起来.(虽然我WA了7次 TLE了3次,被自己蠢哭) 我们观察到 0 <= f[i] <= 6 就简单了,就像小学初中学的 ...

  9. UVA 12012 Detection of Extraterrestrial(KMP求循环节)

    题目描述 E.T. Inc. employs Maryanna as alien signal researcher. To identify possible alien signals and b ...

随机推荐

  1. Cocos2d-x开发实例:使用Lambda 表达式

    在Cocos2d-x 3.0之后提供了对C++11标准[1]的支持,其中的Lambda[2]表达式使用起来非常简洁.我们可以使用Lambda表达式重构上一节的实例. 我们可以将下面的代码: liste ...

  2. Page 的生命周期学习小结(翻译兼笔记)

    初始化(Initialization) 页面被请求时,第一个被执行的总是下面接着执行的是 接着是 然后是 恢复和加载(Restore and Load) 接下来的 ViewState 被取回后,接着  ...

  3. HTML标签语义化

    标签语义化 Web语义化是指使用语义恰当的标签,使页面有良好的结构,页面元素有含义,能够让人和搜索引擎都容易理解. 如果可以在合适的位置使用恰当的标签,那么写出来的页面语义明确,结构清晰,搜索引擎也可 ...

  4. feature.shape和feature.shapecopy的区别

    以前在写AE代码的时候也没有注意到feature.shape和feature.shapecopy的区别,觉得两者也差不多: 今天写入库程序才明白过来. 如果取feature.shape,则得到的是该要 ...

  5. 膜拜 2014-2 (献给L之三)

    文/安然 深深的夜静静的想你细细的品味满满的甜蜜爱,心灵的对话让我流泪战栗谢谢你给我这么弥足珍贵的体会不能一生相随又有什么关系你一直都在我的爱就永不停息此生足以——献给心底的爱

  6. 暑假集训(4)第六弹——— 组合(poj1067)

    题意概括:上一次,你成功甩掉了fff机械兵.不过,你们也浪费了相当多的时间.fff团已经将你们团团包围,并且逐步 逼近你们的所在地.面对如此危机,你不由得悲观地想:难道这acm之路就要从此中断?虽然走 ...

  7. Tomcat虚拟目录的设置

    在学习JSP/Servlet的过程中,配置Tomcat的虚拟目录可能是我们遇到的第一个比较麻烦的问题,说是麻烦是针对我们初学者而言,对于高手那都不是问题.反正我是弄了一天才配置好,发现网上给出的很多配 ...

  8. WinSCP列出’/’目录项出错

    无法获得目录列表 如图所示,使用百度云虚拟机时,FTP连接服务器,出现错提示,官方给出的说法是使用其他的FTP进行连接,但是之前成功连接过,查找资料后说是打开过png,mp3等媒体文件,切换路径时出错 ...

  9. 用C#对ADO.NET数据库完成简单操作

    数据库访问是程序中应用最普遍的部分.随着C#和ADO.NET的引入,这种操作变得更简单.这篇文章将示范四种最基础的数据库操作. ● 读取数据.其中包括多种数据类型:整型,字符串,日期型. ● 写数据. ...

  10. 分享一个很好用的 日期选择控件datepicker 使用方法分享

    很多同学在做网站的时候,有时候需要用户选择日期,年月日这些的,以前我也在用一个,但是那个的界面都不太好看,于是找啊找,找啊找,找到一个好东西,就是这个,datepicker,是jquery.ui里面的 ...