题目:http://acm.hdu.edu.cn/showproblem.php?pid=3977

题意:求斐波那契数列模p的循环节长度,注意p最大是2*10^9,但是它的素因子小于10^6。

分析过程:首先我们知道fib数列模p如果出现了连续的1,0就意味这着开始循环了,因为接下来的项就是1 1 2 3 5等等。

那么很显然如果在第k位第一次出现了1,0,那么对于以后的1,0都可以表示为k*m。

那么,现在我们考虑如果fib数列模p在第pos位第一次出现了0,那么设0前面的那个数为a,则接下来的序列将是a,0,a,

a,2a,3a,5a,8a,....。可以看出a的系数就是一个fib数列,那么我们就可以得到fib(k+i)%p=a*fib(i)%p,其中i满

足0<i<k,所以进一步可以得到fib(i)=[a^j*fib(i-k*j)]%p。

那么我们现在先来说说如何求fib数模一个正整数n的循环节长度:

对于这个问题,我们先对n进行素因子分解,得到:,然后先对每一个形如p^k的数计算循环节,然后它们

的最小公倍数就是n的循环节长度(当然这里面涉及到CRT等等方面的基础)。那么现在问题就是计算p^k的循环节,这个问题

可以进一步简化成求G(p)*p^(k-1)。其中G(p)表示fib数列模素数p的循环节长度,所以现在的问题是如何求fib数列模一个

小于10^6的素数p的循环节长度。

求fib数列模p(p是素数)的最小循环节方法:

暴力枚举fib[i]%p==0的最小的i,然后记录pos=i+1,设a为fib[i]%p==0的前一位数,即a=fib[i-1]

那么我们知道fib数列模p的最小循环节长度一定是pos*x,那么也就是说现在要求一个最小的数x,满足,

求出x后,那么问题就解决了,剩下的就是合并等等。

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h> using namespace std;
typedef long long LL;
const int N=1000005; bool prime[N];
int p[N];
int pri[N];
int num[N];
int f[N];
int fac[N];
int arr[N];
int k,cnt; void isprime()
{
k=0;
int i,j;
memset(prime,true,sizeof(prime));
for(i=2; i<N; i++)
{
if(prime[i])
{
p[k++]=i;
for(j=i+i; j<N; j+=i)
{
prime[j]=false;
}
}
}
} void Solve(LL n)
{
cnt=0;
int ct=0;
int t=(int)sqrt(n*1.0);
for(int i=0; p[i]<=t; i++)
{
if(n%p[i]==0)
{
ct=0;
pri[cnt]=p[i];
while(n%p[i]==0)
{
ct++;
n/=p[i];
}
num[cnt]=ct;
cnt++;
}
}
if(n>1)
{
pri[cnt]=n;
num[cnt]=1;
cnt++;
}
} LL gcd(LL a,LL b)
{
return b? gcd(b,a%b):a;
} LL quick_mod(LL a,LL b,LL m)
{
LL ans=1;
a%=m;
while(b)
{
if(b&1)
{
ans=ans*a%m;
b--;
}
b>>=1;
a=a*a%m;
}
return ans;
} int main()
{
isprime();
int T,a,pos,tt=1;
LL n;
cin>>T;
while(T--)
{
cin>>n;
printf("Case #%d: ",tt++);
Solve(n);
pos=0;
for(int k=0; k<cnt; k++)
{
f[0]=f[1]=1;
for(int i=2;; i++)
{
f[i]=(f[i-1]+f[i-2])%pri[k];
if(f[i]==0)
{
a=f[i-1];
pos=i+1;
break;
}
}
int cv=0;
int tmp=pri[k]-1;
int t=(int)sqrt(tmp*1.0);
for(int i=1; i<=t; i++)
{
if(tmp%i==0)
{
if(tmp/i==i)
fac[cv++]=i;
else
{
fac[cv++]=i;
fac[cv++]=tmp/i;
}
}
}
int record=0;
sort(fac,fac+cv);
for(int i=0; i<cv; i++)
{
if(quick_mod(a,fac[i],pri[k])==1)
{
record=fac[i];
break;
}
}
LL ans=record*pos;
for(int i=1; i<num[k]; i++)
ans*=pri[k];
arr[k]=ans;
}
LL ret=1;
for(int i=0; i<cnt; i++)
ret=ret/gcd(ret,arr[i])*arr[i];
cout<<ret<<endl;
}
return 0;
}

HDU3977(斐波那契数列模n的循环节长度)的更多相关文章

  1. HPU 1471:又是斐波那契数列??(大数取模)

    1471: 又是斐波那契数列?? 时间限制: 1 Sec 内存限制: 128 MB 提交: 278 解决: 27 统计 题目描述 大家都知道斐波那契数列吧?斐波那契数列的定义是这样的: f0 = 0; ...

  2. 2018年东北农业大学春季校赛 K wyh的数列【数论/斐波那契数列大数取模/循环节】

    链接:https://www.nowcoder.com/acm/contest/93/K来源:牛客网 题目描述 wyh学长特别喜欢斐波那契数列,F(0)=0,F(1)=1,F(n)=F(n-1)+F( ...

  3. HDU4549 M斐波那契数列 矩阵快速幂+欧拉函数+欧拉定理

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

  4. HDU----(4549)M斐波那契数列(小费马引理+快速矩阵幂)

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

  5. [HDU 4549] M斐波那契数列

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

  6. [BSGS算法]纯水斐波那契数列

    学弟在OJ上加了道"非水斐波那契数列",求斐波那契第n项对1,000,000,007取模的值,n<=10^15,随便水过后我决定加一道升级版,说是升级版,其实也没什么变化,只 ...

  7. 斐波那契数列(NOIP1997)

    题目链接:斐波那契数列 这题是数论的一个基本应用,还是很水,因为数据范围太水了,只有48,这也太小了.不过也有可能是当时的电脑速度跑得比较慢的原因.但是这个算法应该还是这个算法.主要思路就是递推求斐波 ...

  8. M斐波那契数列(矩阵快速幂+费马小定理)

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

  9. hdu 4549 M斐波那契数列 矩阵快速幂+欧拉定理

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Problem ...

随机推荐

  1. CCNP交换实验(5) -- 网关热备冗余

    HSRP:1.启用HSRP功能,并设置虚拟地址IP, 1为standby的组号.2.相同组号的路由器属于同一个HSRP组,所有属于同一个HSRP组的路由器的虚拟地址必须一致.3.HSRP的优先级默认为 ...

  2. Android程序检测网络是否可用

    在做Android应用程序中,连接网络的时候,常常要用到检测网络状态是否可用,在这里分享一个比较好用的方法. 本人参考:http://blog.csdn.net/sunboy_2050/article ...

  3. FORM验证简单demo

    详解稍后加入. 项目结构如图: web.xml <?xml version="1.0" encoding="UTF-8" ?> <web-ap ...

  4. Linux IP代理筛选系统(shell+proxy)

    代理的用途 其实,除了抓取国外网页需要用到IP代理外,还有很多场景会用到代理: 通过代理访问一些国外网站,绕过被某国防火墙过滤掉的网站 使用教育网的代理服务器,可以访问到大学或科研院所的内部网站资源 ...

  5. libevent简单分析

    一看名字就知道是围绕eventloop转的. 那首先肯定是eventloop是个什么?一般都是IO事件,timer事件的管理器. 那首先看如何new出来一个eventloop: 1.因为libeven ...

  6. javacsript (十) 数据类型

    类型声明的时候,直接使用 var  varname=xxx 数字.字符.布尔,声明都直接使用var就可以, JavaScript 数组 下面的代码创建名为 cars 的数组: var cars=new ...

  7. form表单提交不成功提示

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...

  8. 使用Elasticsearch、Logstash、Kibana与Redis(作为缓冲区)对Nginx日志进行收集(转)

    摘要 使用Elasticsearch.Logstash.Kibana与Redis(作为缓冲区)对Nginx日志进行收集 版本 elasticsearch版本: elasticsearch-2.2.0 ...

  9. C语言中输入输出重定,freopen()妙用。

    使用的理由(范围):如果输入数据很庞大,需要一次又一次的重新输入和调试时可采用本函数. freopen ()函数: 1.格式 FILE * freopen ( const char * filenam ...

  10. DotNetBar怎样控制窗口样式

    DotNetBar怎样控制窗口样式 老帅  在C#中使用控件DevComponents.DotNetBar时,怎样创建一个美丽的窗口.并控制窗口样式呢? 1.新建一个DotNetBar窗口       ...