专栏文章
题解:P5136 sequence
P5136题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @miqc96kn
- 此快照首次捕获于
- 2025/12/04 02:26 3 个月前
- 此快照最后确认于
- 2025/12/04 02:26 3 个月前
本蒟蒻通过的第一道紫题,连夜肝出题解纪念。
思路
前置芝士:
Lucas 数列
Lucas 数列
首先题目给出的数为 ,求 的 次幂并向上取整。题目背景也提到了数列,基于此不难想到斐波那契数列。
我们设 ,。
Lucas 数列的递推式为 ,通项式为 。
据此我们易知 ,注意到 ,所以 ,因此 ,代入具体数字:
- ,
- ,
- ……
我们知道,当 时,;否则 。
也就是说当 为奇数时 ,否则
也就是说当 为奇数时 ,否则
注意到题目要求的是 ,上文我们已经求出了 ,所以在 的情况下对结果无影响;在 的情况下,需要加上 。
综上所述,结论已经呼之欲出了,。
现在我们只需要计算 Lucas 数列便可以了,聪明的你一定想到计算方法 ---- 矩阵快速幂! 构造矩阵的方法就不介绍了。
现在我们只需要计算 Lucas 数列便可以了,聪明的你一定想到计算方法 ---- 矩阵快速幂! 构造矩阵的方法就不介绍了。
代码
矩阵快速幂的代码模板采用的是这个。
越界优化版
CPP
#include<bits/stdc++.h>
#define int long long
#define N 3
#define MOD 998244353
using namespace std;
int base[N][N],tmp[N][N],n;
inline void Init();
inline void mult(int x[N][N],int y[N][N]);
inline int fpow(int b);
inline void read(int &num);
signed main(){
int T;
read(T);
while(T--){
Init();
read(n);
int res=fpow(n-1);
if(n&1)++res;
printf("%lld\n",res%MOD);
}
}
inline void Init(){
base[1][1]=0;
base[1][2]=1;
base[2][1]=1;
base[2][2]=1;
}
inline void mult(int x[N][N],int y[N][N]){
int tmp[N][N];
for(int i=1;i<N;++i){
for(int j=1;j<N;++j){
tmp[i][j]=0;
for(int k=1;k<N;++k){
tmp[i][j]=(tmp[i][j]+x[i][k]*y[k][j])%MOD;
}
}
}
memcpy(x,tmp,sizeof(tmp));
}
inline int fpow(int b){
int ans[N][N];
for(int i=1;i<N;++i){
for(int j=1;j<N;++j){
ans[i][j]=1;
}
}
ans[1][1]=1;
ans[1][2]=3;
while(b){
if(b&1)mult(ans,base);
mult(base,base);
b/=2;
}
return ans[1][1];
}
inline void read(int &num){
int x=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
num=x*f;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...