关于3B1B特征向量那一节斐波那契用矩阵求解问题

Posted ~画风人~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于3B1B特征向量那一节斐波那契用矩阵求解问题相关的知识,希望对你有一定的参考价值。

我们知道对于矩阵 \\(A^n\\),它可以通过特征向量的线性组合来进行相似对角化,先\\(D = PAP^-1\\)\\(A = PD^nP^-1\\),其中 \\(D\\) 是一个由特征值组成的对角矩阵,\\(P = [v_1, v_2]\\) 是一个包含线性无关的特征向量的矩阵。

对于矩阵 \\(A = \\beginbmatrix0 & 1 \\\\ 1 & 1\\endbmatrix\\),我们已经求出了两个线性无关的特征向量:

\\[v_1 = \\beginbmatrix2 \\\\ 1 + \\sqrt5\\endbmatrix, \\quad v_2 = \\beginbmatrix2 \\\\ 1 - \\sqrt5\\endbmatrix. \\]

把这两个向量按列排成矩阵 \\(P\\)

\\[P = \\beginbmatrix2 & 2 \\\\ 1 + \\sqrt5 & 1 - \\sqrt5\\endbmatrix. \\]

矩阵 \\(P^-1\\) 可以通过求 \\(P\\) 的逆矩阵得到:

\\[P^-1 = -\\frac14\\sqrt5 \\beginbmatrix1 - \\sqrt5 & -2 \\\\ -1 - \\sqrt5 & 2 \\endbmatrix. \\]

我们有 \\(D = PAP^-1\\),其中

\\[D = \\beginbmatrix\\lambda_1 & 0 \\\\ 0 & \\lambda_2\\endbmatrix = \\beginbmatrix\\frac1 + \\sqrt52 & 0 \\\\ 0 & \\frac1 - \\sqrt52\\endbmatrix \\]

是特征值组成的对角矩阵。

我们可以把 \\(A^n\\) 表示为 \\(PD^nP^-1\\)。由于 \\(D\\) 是对角矩阵,我们可以直接将 \\(D\\) 的每个元素取 \\(n\\) 次幂:

\\[D^n = \\beginbmatrix\\left(\\frac1 + \\sqrt52\\right)^n & 0 \\\\ 0 & \\left(\\frac1 - \\sqrt52\\right)^n\\endbmatrix. \\]

然后再将 \\(D^n\\) 代入 \\(PD^nP^-1\\),得到:

\\[A^n = P\\beginbmatrix\\left(\\frac1 + \\sqrt52\\right)^n & 0 \\\\ 0 & \\left(\\frac1 - \\sqrt52\\right)^n\\endbmatrixP^-1 = \\frac14\\sqrt5\\beginbmatrix2(\\sqrt5-1)\\left(\\dfrac1+\\sqrt52\\right)^n + 2(1+\\sqrt5)\\left(\\dfrac1-\\sqrt52\\right)^n & 4\\left(\\dfrac1+\\sqrt52\\right)^n - 4\\left(\\dfrac1-\\sqrt52\\right)^n \\\\ 4\\left(\\dfrac1+\\sqrt52\\right)^n - 4\\left(\\dfrac1-\\sqrt52\\right)^n & 2(1+\\sqrt5)\\left(\\dfrac1+\\sqrt52\\right)^n - 2(1-\\sqrt5)\\left(\\dfrac1-\\sqrt52\\right)^n\\endbmatrix. \\]

下面是完整的 \\(A^n\\) 的表达式:

\\[A^n = P\\beginbmatrix\\left(\\frac1 + \\sqrt52\\right)^n & 0 \\\\ 0 & \\left(\\frac1 - \\sqrt52\\right)^n\\endbmatrixP^-1 = \\frac1\\sqrt5\\beginbmatrix\\left(\\dfrac1+\\sqrt52\\right)^n-1 - \\left(\\dfrac1-\\sqrt52\\right)^n-1 & \\left(\\dfrac1+\\sqrt52\\right)^n - \\left(\\dfrac1-\\sqrt52\\right)^n \\\\ \\left(\\dfrac1+\\sqrt52\\right)^n - \\left(\\dfrac1-\\sqrt52\\right)^n & \\left(\\dfrac1+\\sqrt52\\right)^n+1 - \\left(\\dfrac1-\\sqrt52\\right)^n+1\\endbmatrix. \\]

交换特征向量

那一开始那个地方的\\(P = [v_1, v_2]\\)这里可否换成\\(P = [v_2, v_1]\\)
由于我没学过线代只听过3b1b的课,对原理什么都不懂,所以我这里就直接算,算完看看结果咋样

在本题中,将 \\(P\\) 中的顺序进行交换后,矩阵 \\(P\\) 和其逆矩阵 \\(P^-1\\) 的计算结果分别为:

\\[P^-1=\\frac14\\sqrt5\\beginpmatrix 1+\\sqrt5 & -2 \\\\ \\sqrt5-1 & 2 \\endpmatrix. \\]

特征值反了过来

\\[D = \\beginbmatrix\\frac1 - \\sqrt52 & 0 \\\\ 0 & \\frac1 + \\sqrt52\\endbmatrix \\]

\\[D^n = \\beginbmatrix\\left(\\frac1 - \\sqrt52\\right)^n & 0 \\\\ 0 & \\left(\\frac1 + \\sqrt52\\right)^n\\endbmatrix. \\]

接下来,我们可以按照 \\(P\\)\\(P^-1\\) 的结果,计算 \\(A^n\\) 的表达式:

结果很惊讶,第一次算 得出的结果居然和[v1,v2]一样

\\[A^n = P\\beginbmatrix\\left(\\frac1 - \\sqrt52\\right)^n & 0 \\\\ 0 & \\left(\\frac1 + \\sqrt52\\right)^n\\endbmatrixP^-1 = \\frac1\\sqrt5\\beginbmatrix\\left(\\dfrac1+\\sqrt52\\right)^n-1 - \\left(\\dfrac1-\\sqrt52\\right)^n-1 & \\left(\\dfrac1+\\sqrt52\\right)^n - \\left(\\dfrac1-\\sqrt52\\right)^n \\\\ \\left(\\dfrac1+\\sqrt52\\right)^n - \\left(\\dfrac1-\\sqrt52\\right)^n & \\left(\\dfrac1+\\sqrt52\\right)^n+1 - \\left(\\dfrac1-\\sqrt52\\right)^n+1\\endbmatrix. \\]

也就是说这里不管p[v1,v2]或者p[v2,v1]两者都可以,跟顺序无关。
最后再说一下,md语法写数学公式是真的麻烦,一大堆难免有符号之类的错误,如果有错误希望各位大佬能指正。

附上md写数学公式的图

斐波那契数列小结

关于斐波那契数列,相信大家对它并不陌生,关于其的题目也不在少数。

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

基础问题

1.求斐波那契数列的第k项

常规方法是利用f[i]=f[i-1]+f[i-2],时间复杂度为O(n)

显然最多处理到1e7

假如n到1e18怎么办,O(n)显然就T飞了.

我们考虑利用什么方法来加速

斐波那契数列数列是其次线性递推式

所以是可以利用矩阵乘法进行求解的

$$ left [ egin{matrix} 1 & 1 \\ 1 & 0  end{matrix} ight] ag{2}  $$ 

很显然用[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的时间求斐波那契数列的循环节

综合问题

洛谷4000

求一个循环节,然后矩阵快速幂,就是一个模板的合集

// 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;
}

  

 

以上是关于关于3B1B特征向量那一节斐波那契用矩阵求解问题的主要内容,如果未能解决你的问题,请参考以下文章

斐波那契数列以及斐波那契数列的衍生形式 利用矩阵快速幂求解

[板子]矩阵快速幂求解斐波那契

斐波那契数列小结

矩阵乘法求解多项式递推问题

动态规划-第一节2:动态规划之使用“斐波那契数列”问题说明重叠子问题如何解决

用递归和非递归方法求解斐波那契数列