2024-07-16 21:01阅读: 5评论: 0推荐: 0

[ABC258Ex] Odd Steps 题解

思路

拿到这道题,第一时间肯定想到是 dp 题目。

朴素 DP

dpi 表示序列和为 i 的序列个数。因为原数组由奇数组成,所以 dp 只可能由 dpi1dpi3 等等转移过来,若 iAdpi=0。即:

dpi={0iAdpi1+dpi3+otherwise

优化

sumi=fi+fi2+fi4+。则 $f_i=sum_{i-1} s_i=s_{i-2}+f_i$。

观察式子发现可以使用矩阵优化递推,我们维护 fisumi1sumi2 的值。

因为 :

{fi+1=fi+si2si=fi+si2si2=si2

所以可以构造如下矩阵:

[fisi1si2][110001110]

所以之后分段快速幂即可,剩下的看我代码吧。

代码

#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 中国大陆许可协议进行许可。

posted @   merlinkkk  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开