[ABC258Ex] Odd Steps 题解
思路
拿到这道题,第一时间肯定想到是 题目。
朴素 DP
用 表示序列和为 的序列个数。因为原数组由奇数组成,所以 只可能由 , 等等转移过来,若 ,。即:
优化
设 。则 $f_i=sum_{i-1} s_i=s_{i-2}+f_i$。
观察式子发现可以使用矩阵优化递推,我们维护 ,, 的值。
因为 :
所以可以构造如下矩阵:
所以之后分段快速幂即可,剩下的看我代码吧。
代码
#include<bits/stdc++.h> using namespace std; #define int long long const int maxn=3, mod=998244353; int a[100010]; struct mat { int a[maxn+1][maxn+1]; mat() { memset(a,0,sizeof(a)); } mat operator*(const mat&T) const { mat res; for(int i=1;i<=maxn;i++) { for(int j=1;j<=maxn;j++) { for(int k=1;k<=maxn;k++) { res.a[i][j]=(res.a[i][j]+a[i][k]*T.a[k][j])%mod; } } } return res; } mat operator^(int x) const { mat bas,res; for(int i=1;i<=maxn;i++) res.a[i][i]=1; for(int i=1;i<=maxn;i++) { for(int j=1;j<=maxn;j++) { bas.a[i][j]=a[i][j]%mod; } } while(x) { if(x&1) { res=res*bas; } bas=bas*bas; x>>=1; } return res; } }; mat x,y,tmp; signed main() { x.a[1][1]=1, x.a[1][2]=0,x.a[1][3]=0; int n,s; cin>>n>>s; y.a[1][1]=y.a[1][2]=y.a[2][3]=y.a[3][2]=y.a[3][1]=1; for(int i=1;i<=n;i++) { cin>>a[i]; tmp=y^(a[i]-a[i-1]); x=x*tmp; x.a[1][1]=0; } mat tmp=y^(s-a[n]); x=x*tmp; cout<<x.a[1][1]; return 0; }
本文作者:merlinkkk
本文链接:https://www.cnblogs.com/merlinkkk/p/18306104
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步