蓝桥杯 算法提高 递推求值

Posted 天道铸魂

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯 算法提高 递推求值相关的知识,希望对你有一定的参考价值。

题目如下:

问题描述
  已知递推公式:

  F(n, 1)=F(n-1, 2) + 2F(n-3, 1) + 5,

  F(n, 2)=F(n-1, 1) + 3F(n-3, 1) + 2F(n-3, 2) + 3.

  初始值为:F(1, 1)=2, F(1, 2)=3, F(2, 1)=1, F(2, 2)=4, F(3, 1)=6, F(3, 2)=5。
  输入n,输出F(n, 1)和F(n, 2),由于答案可能很大,你只需要输出答案除以99999999的余数。
输入格式
  输入第一行包含一个整数n。
输出格式
  输出两行,第一行为F(n, 1)除以99999999的余数,第二行为F(n, 2)除以99999999的余数。
样例输入
4
样例输出
14

21
数据规模和约定
  1<=n<=10^18。
-----分割线-----
  在拿到此题后,就知道这题应该是矩阵快速幂,但是因为以前只做过简单的斐波那契数列的矩阵快速幂,所以完全不知道这题该怎么构造矩阵,后来翻了百度上的很多博客。简单来说,就是找到一个矩阵A满足:x(n-1)*A=x(n)。当然,此题不同于一般的“x(n)、x(n-1)”。要做如下构造:
  [f(n-1,1),f(n-1,2),f(n-2,1),f(n-2,2),f(n-3,1),f(n-3,2),5,3]*A=[f(n,1),f(n,2),f(n-1,1),f(n-1,2),f(n-2,1),f(n-2,2),5,3]
  即把前三项当做x(n-1),后一项以及前三项的后两项当做x(n),易知矩阵为8阶矩阵,具体见代码:
#include<stdio.h>
#define max 99999999
#define ll long long int
typedef struct Matrix
{
    ll m[8][8];
}mat;
mat multi(mat x,mat y,int a,int b,int c)
{
    int i,j,k;
    mat z;
    for(i=0;i<8;i++)
        for(j=0;j<8;j++)
            z.m[i][j]=0;
    for(i=0;i<a;i++)
        for(j=0;j<c;j++)
            for(k=0;k<b;k++)
                z.m[i][j]=(z.m[i][j]+(x.m[i][k]*y.m[k][j])%max)%max;
    return z;
}
int main()
{
    ll n,v1,v2,i;
    mat A={ 0,1,1,0,0,0,0,0,
            1,0,0,1,0,0,0,0,
            0,0,0,0,1,0,0,0,
            0,0,0,0,0,1,0,0,
            2,3,0,0,0,0,0,0,
            0,2,0,0,0,0,0,0,
            1,0,0,0,0,0,1,0,
            0,1,0,0,0,0,0,1
                            };
    mat E={ 1,0,0,0,0,0,0,0,
            0,1,0,0,0,0,0,0,
            0,0,1,0,0,0,0,0,
            0,0,0,1,0,0,0,0,
            0,0,0,0,1,0,0,0,
            0,0,0,0,0,1,0,0,
            0,0,0,0,0,0,1,0,
            0,0,0,0,0,0,0,1,
                            };
    ll s[8]={6,5,1,4,2,3,5,3};
    scanf("%I64d",&n);
    if(n==1)
        printf("2\n3");
    if(n==2)
        printf("1\n4");
    if(n==3)
        printf("6\n5");
    if(n>=4)
    {
        n-=3;
        while(n)
        {
            if(n%2)
                E=multi(E,A,8,8,8);
            n/=2;
            A=multi(A,A,8,8,8);
        }
        v1=0;
        v2=0;
        for(i=0;i<8;i++)
        {
            v1=(v1+(s[i]*E.m[i][0])%max)%max;
            v2=(v2+(s[i]*E.m[i][1])%max)%max;
        }
        printf("%I64d\n%I64d",v1,v2);
    }
    return 0;
}

 

以上是关于蓝桥杯 算法提高 递推求值的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥杯java 算法提高 邮票面值设计

java 蓝桥杯算法提高 字串统计

蓝桥杯 算法提高 盾神与条状项链

递推求值快速幂矩阵

蓝桥杯 算法提高 5-3日历

算法笔记_105:蓝桥杯练习 算法提高 上帝造题五分钟(Java)