强(矩阵快速幂)

题目描述

Lh:粉兔你教我一下抽屉原理吧

Clz:就是给你一个长度为 n 的序列,每个数只能取 0,1,2,那你连续取三个数必然有两个相等……

Lh:等等你梭啥,再说一遍

Clz:……emmm 当我没说

Marser:就是一个序列,对于每一个连续三元组都要满足其中至少有两个相等

现在粉兔问你:有多少个长度为 n 的序列满足粉兔的要求?请对 19260817 取模。

输入

一行一个正整数n(3≤n≤1018)。

输出

一行一个整数,含义如题。

样例输入 Copy

4

样例输出 Copy

51

                                                        

 思路:

令f[n]为长度为n的合法序列数量

假设序列 s-1的末尾两个数相同则s有三种选法,如果不同有两种选法。

s-1末尾相同的选法可以由f[s-2]表示.则f[n]=2*f[n-1]+f[n-2]

想这种类似斐波拉且的递推是,可以用矩阵快速幂优化。

Code:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<unordered_map>
using namespace std;
#define x first
#define y second
#define PII pair<int,int>
#define V vector<int>
#define endl "\n"
typedef long long ll;
typedef unsigned long long llu;
const int INF=0x3f3f3f3f,mod=19260817;
struct matrix 
{
    ll mat[2][2];
    void init() {
        memset(mat,0,sizeof mat);
    }
};
matrix mul(matrix a,matrix b)
{
    matrix c;
    c.init();
    for(int i=0;i<2;i++) {
        for(int j=0;j<2;j++) {
            for(int k=0;k<2;k++) {
                c.mat[i][j]+=(a.mat[i][k]%mod)*(b.mat[k][j]%mod)%mod;
                c.mat[i][j]%=mod;
            }
        }
    }
    return c;     
}
matrix ksm(matrix a,ll n)
{
    matrix b;
    b.init();
    for(int i=0;i<2;i++) b.mat[i][i]=1;
    while(n)
    {
        if(n&1) b=mul(b,a);
        a=mul(a,a);
        n>>=1;
    }
    return b;
}
int main()
{
    //f[n]=2*f[n-1]+f[n-2]
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    ll n;
    cin>>n;
    if(n==3) cout<<21;
    else if(n==4) cout<<51;
    else 
    {
        matrix a,res,ans;
        a.mat[0][0]=2;
        a.mat[0][1]=a.mat[1][0]=1;
        a.mat[1][1]=0;
        res=ksm(a,n-4);
        ans.init();
        ans.mat[0][0]=51;
        ans.mat[0][1]=21;
        ans=mul(ans,res);
        cout<<ans.mat[0][0];
    }
    return 0;
}

形如:f[n]=a*f[n-1]+b*f[n-2]+c

可用矩阵乘积形式表示

\bigl(\begin{smallmatrix} f(n)\\f(n-1) \\ c \end{smallmatrix}\bigr)=\bigl(\begin{smallmatrix} a& b & 1\\ 1& 0 &0 \\ 0& 0 & 1 \end{smallmatrix}\bigr)\bigl(\begin{smallmatrix} f(n-1)\\f(n-2) \\ c \end{smallmatrix}\bigr)

形如:f[n]=c^n-f[n-1]

\bigl(\begin{smallmatrix} f(n)\\c^n \end{smallmatrix}\bigr)=\bigl(\begin{smallmatrix} -1 &c \\ 0& c \end{smallmatrix}\bigr)\bigl(\begin{smallmatrix} f(n-1)\\c^{n-1} \end{smallmatrix}\bigr)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值