斐波那契数列小结

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

斐波那契数列⼩结关于斐波那契数列,相信⼤家对它并不陌⽣,关于其的题⽬也不在少数。

我现在总结⼀下有关它的⼀些有趣的性质。

基础问题
1.求斐波那契数列的第k项
常规⽅法是利⽤f[i]=f[i-1]+f[i-2],时间复杂度为O(n)
显然最多处理到1e7
假如n到1e18怎么办,O(n)显然就T飞了.
我们考虑利⽤什么⽅法来加速
斐波那契数列数列是其次线性递推式
所以是可以利⽤矩阵乘法进⾏求解的
[]
11
10
很显然⽤[Fi,F(i-1)]乘以上⾯的矩阵是可以得到[Fi+F(i-1),Fi]
这样,再利⽤矩阵快速幂就可以做到8logn求解斐波那契数列第n项了
2.
求Fi与Fj的最⼤公约数
这⾥要⽤到⼀个神奇的性质
gcd(F[n],F[m])=F[gcd(n,m)]
证明:
这⾥的结论可以记下来,可能会有⽤
3.斐波那契数列的循环节
求斐波那契数列modn的循环节
,我们可以在logp的时间求斐波那契数列的循环节
综合问题
求⼀个循环节,然后矩阵快速幂,就是⼀个模板的合集
// luogu-judger-enable-o2
# include<cstring>
# include<iostream>
# include<cstdio>
# include<cmath>
# include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll dp[maxn*10];
ll prime[maxn],s=0;
bool vis[maxn];
char ch[30000005];
int len;
void init_prime()
{
for(ll i=2;i<maxn;i++)
{
if(!vis[i]) prime[s++]=i;
for (ll j=0;j<s&&i*prime[j]<maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
return;
}
ll pow_mod(ll a1,ll b1)
{
ll ans=1;
while(b1)
{
if(b1&1) ans=ans*a1;
b1>>=1;
a1*=a1;
}
return ans;
}
ll pow_mod2(ll a,ll b,ll p)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%p;
b>>=1;
a=a*a%p;
}
return ans;
}
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
bool f(ll n,ll p)
{
return pow_mod2(n,(p-1)>>1,p)==1;
}
struct matrix
{
ll x1,x2,x3,x4;
};
matrix matrix_a,matrix_b,matrix_c;
matrix M2(matrix aa,matrix bb,ll mod)
{
matrix tmp;
tmp.x1=(aa.x1*bb.x1%mod+aa.x2*bb.x3%mod)%mod; tmp.x2=(aa.x1*bb.x2%mod+aa.x2*bb.x4%mod)%mod; tmp.x3=(aa.x3*bb.x1%mod+aa.x4*bb.x3%mod)%mod; tmp.x4=(aa.x3*bb.x2%mod+aa.x4*bb.x4%mod)%mod; return tmp;
}
matrix M(ll n,ll mod)
{
matrix a,b;
a=matrix_a;b=matrix_b;
while(n){
if(n&1){
b=M2(b,a,mod);
}
n>>=1;
a=M2(a,a,mod);
}
return b;
}
ll fac[100][2],l,x,fs[1000];
void dfs(ll count,ll step)
{
if(step==l)
{
fs[x++]=count;
return ;
}
ll sum=1;
for(ll i=0;i<fac[step][1];i++)
{
sum*=fac[step][0];
dfs(count*sum,step+1);
}
dfs(count,step+1);
}
ll solve2(ll p)
{
if(p<1e6&&dp[p]) return dp[p];
bool ok=f(5,p);
ll t;
if(ok) t=p-1;
else t=2*p+2;
l=0;
for(ll i=0;i<s;i++)
{
if(prime[i]>t/prime[i]) break;
if(t%prime[i]==0)
{
ll count=0;
fac[l][0]=prime[i];
while(t%prime[i]==0)
{
count++;t/=prime[i];
}
fac[l++][1]=count;
}
}
if(t>1)
{
fac[l][0]=t;
fac[l++][1]=1;
}
x=0;
dfs(1,0);
sort(fs,fs+x);
for(ll i=0;i<x;i++)
{
matrix m1=M(fs[i],p);
if(m1.x1==m1.x4&&m1.x1==1&&m1.x2==m1.x3&&m1.x2==0) {
if(p<1e6) dp[p]=fs[i];
return fs[i];
}
}
}
ll solve(ll n){
ll ans=1,cnt;
for(ll i=0;i<s;i++){
if(prime[i]>n/prime[i]){
break;
}
if(n%prime[i]==0){
ll count=0;
while(n%prime[i]==0){
count++;n/=prime[i];
}
cnt=pow_mod(prime[i],count-1);
cnt*=solve2(prime[i]);
ans=(ans/gcd(ans,cnt))*cnt;
}
}
if(n>1){
cnt=1;
cnt*=solve2(n);
ans=ans/gcd(ans,cnt)*cnt;
}
return ans;
}
void pre()
{
init_prime();
matrix_a.x1=matrix_a.x2=matrix_a.x3=1;
matrix_a.x4=0;
matrix_b.x1=matrix_b.x4=1;
matrix_b.x2=matrix_b.x3=0;
dp[2]=3;dp[3]=8;dp[5]=20;
}
int main(){
ll t,n,MOD,num=0;
pre();
scanf("%s",ch+1);
len=strlen(ch+1);
scanf("%lld",&n);
MOD=solve(n);
for (int i=1;i<=len;i++)
{
num=num*10+ch[i]-'0';
while (num>=MOD) num-=MOD;
}
matrix_c=M(num,n);
printf("%lld",matrix_c.x2);
return 0;
}
Processing math: 100%。

相关文档
最新文档