斐波那契数列相关
斐波那契数列
或,.
广义斐波那契数列在转移时有系数且首两项给定。
求法
注意到斐波那契数列的转移为一个矩阵乘
当然广义斐波那契数列的转移就是把转移矩阵的系数换了一下。
所以我们可以通过矩阵快速幂快速求得所求项数。
给出广义斐波那契数列的矩阵乘代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
int mod;
struct mat{
int a[2][2];
inline void set(){
memset(a,0,sizeof a);
}
inline void zero(){
set();a[0][0]=a[1][1]=1;
}
inline int* operator [] (const int x){return a[x];}
inline const int* operator [] (const int x) const {return a[x];}
inline mat operator * (const mat &b)const{
mat ans;
ans.set();
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
ans[i][j]=(ans[i][j]+a[i][k]*b[k][j]%mod)%mod;
return ans;
}
}now,pow;
inline mat fpow(mat a,int b){
mat ans;
ans.zero();
for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a;
return ans;
}
inline void work(){
int p=read(),q=read(),a1=read(),a2=read(),n=read();
mod=read();
now[0][1]=a1,now[0][0]=a2,pow[0][0]=p,pow[1][0]=q,pow[0][1]=1;
printf("%lld",(now*fpow(pow,n-1))[0][1]);
}
}
signed main(){
star::work();
return 0;
}
性质
斐波那契数具有很多神奇的性质,虽然有些不太常用
- 齐肯多夫定理:任何正整数可以表示为若干个不连续的斐波那契数之和。
于是我们可以引出来一个叫做斐波那契进制的东西。
简单来说,因为任何数都可以被若干个斐波那契数的和表示,我们就可以把这个数用01串表示。其中第i位表示是否含有。
更形式化地讲,从大到小枚举斐波那契数,每当$ F[i] F[i]$,根据定理最后一定会被减完,即被一个01串表示。
因为斐波那契数的增长速度很快,所以这个串并不会很长。
我们来看个毒瘤题:
对于这个LCA的毒瘤题本身我并不会没什么好说的,没有发现打表之外的解法
通过打表我们可以发现,设表示还剩i颗石子时甲必胜此次至少要取的石子个数,那么为在斐波那契进制下的lowbit。
所以这个题本身和斐波那契数就只有这么点关系
对于题本身不予讨论。我也不会证
斐波那契公约数
我们需要证明。
其中。
- 引理:
证明:
即与互质。
- 引理:
设,向下递推发现由和表达的中其系数是斐波那契数。自己推推就知道了。
证明:
不妨设,则有
即
递归求解,发现我们就是在对F的下标求gcd,也就是
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int mod=1e8;
struct mat{
int a[2][2];
mat(){
memset(a,0,sizeof a);
}
inline void zero(){
a[0][0]=a[1][1]=1;
}
inline int* operator [] (const int x){return a[x];}
inline const int* operator [] (const int x) const {return a[x];}
inline friend mat operator * (const mat &a,const mat &b){
mat ans;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
ans[i][j]=(ans[i][j]+a[i][k]*b[k][j]%mod)%mod;
return ans;
}
}now,pow;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline mat fpow(mat a,int b){
mat ans;
ans.zero();
for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a;
return ans;
}
inline void work(){
now[0][0]=now[0][1]=pow[0][0]=pow[0][1]=pow[1][0]=1;
printf("%lld",(now*fpow(pow,gcd(read(),read())-1))[0][1]);
}
}
signed main(){
star::work();
return 0;
}
还是设,然后推来推去,具体看@浅色调 的过程
对于P3986,这个结论可以用来快速解决而不用exgcd。
即有通解
贴下P3986的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<cmath>
#define int long long
using namespace std;
inline int read(){
int w=0,x=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace star
{
const int maxn=100,mod=1e9+7;
int N,f[maxn],ans;
inline void work(){
int k=read();
f[1]=f[2]=1;ans=k-1;
for(N=3;(f[N]=f[N-1]+f[N-2])<k;N++);
N--;
for(int x,y,j=2;j<=N;j++){
int q=((j-1)&1)?-1:1;
x=k*q*f[j+3],y=-k*q*f[j+2];
if(x<0){
y-=((-x)/f[j+1]+1)*f[j];
if(y>0)ans=(ans+(int)ceil(1.0*y/f[j]))%mod;
}else
if(y<0){
x-=((-y)/f[j]+1)*f[j+1];
if(x>0)ans=(ans+(int)ceil(1.0*x/f[j+1]))%mod;
}
}
printf("%lld",ans);
}
}
signed main(){
star::work();
return 0;
}
PS:浅色调的题解对N多算了一次,减掉即可。或者在第二遍for循环内直接判掉break也行。
UPD10.15
- 给定一个长为n的序列,可在其中填1,求使1任意两个都不相邻的方案数。
昨天看了一道叫做01矩阵的题目想到该问题,经询问luogu聚铑们得到答案。
首先,
这玩意和斐波那契数有什么关系?
考虑DP,对于位置,设为前i个数填完、i填0或1的方案数,则有转移
设为到i的方案总数,则有
和斐波那契数列的转移相同。
总结
斐波那契数列性质很多。之后遇到新的我应该会补。
如果您凑巧看到了这里并知道一些相关题目请不吝赐教~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现