思路来源
https://blog.csdn.net/Originum/article/details/82111066
板子
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int mod=998244353;
struct mat{
static const int N=2;
ll c[N][N];
int m,n;
mat(){
memset(c,0,sizeof(c));
m=n=N;
}
mat(int a,int b):m(a),n(b){
memset(c,0,sizeof(c));
}
void clear(){
memset(c,0,sizeof(c));
}
void E(){
int mn=min(m,n);
for(int i=0;i<mn;i++){
c[i][i]=1;
}
}
mat operator *(const mat& x){
mat ans(m,x.n);
for(int i=0;i<m;i++)
for (int k=0;k<n;k++)
{
if(!c[i][k])continue;//小剪枝
for (int j=0;j<x.n;j++)
(ans.c[i][j]+=c[i][k]*x.c[k][j]%mod)%=mod;//能不取模 尽量不取模
}
//这里maxn=2 故不会超过ll 视具体情况 改变内部取模情况
return ans;
}
friend mat operator^(mat x,ll n){//幂次一般为ll 调用时a=a^(b,n) 等价于a=b^n
mat ans(x.m, x.m);
ans.E();
for(;n;n>>=1,x=x*x){//x自乘部分可以预处理倍增,也可以用分块加速递推
if(n&1)ans=ans*x;
}
return ans;
}
}