AT_abc258_h [ABC258Ex] Odd Steps 题解

题目没有要求 \(X\) 的元素个数之类的,导致 \(X\) 的限制非常少,注意到“限制是性质”,这也意味着 \(X\) 的性质非常少,我们不好下手,转而看 \(A\) 。非常自然的想法就是容斥dp,把 \(S\) 放到 \(A\) 的最后一个元素,令 \(dp_i\) 表示目前 \(X\) 的和等于 \(A_i\) ,\(i\) 之前的限制都满足的方案数,则转移方程为 $$dp_i=F_{A_i}-\sum{dp_j*F_{A_i-A_j}}$$ 其中 \(F_i\) 表示 \(i\) 的奇数拆分数,打表发现 \(F_i\) 恰好就是斐波那契数列。

证明:构建一个奇数数列使其和为 \(i\) ,可以使用以下两种操作
1.在数列末尾新加入一个 \(1\)
2.令数列末尾的数加上 \(2\)
于是 \(F_i=F_{i-1}+F_{i-2}\) ,刚好满足斐波那契的形式

所以 \(F\) 数组就可以直接矩阵快速幂求出,至于 \(dp\) 数组,同样使用矩阵快速幂。
我们枚举到 \(i-1\) 时设一个向量

\[V=\begin{pmatrix} \sum{dp_{i-1}*F_{A_{i-1}-A_j}} &\sum{dp_{i-1}*F_{A_{i-1}-A_j-1}} ) \end{pmatrix}\]

然后用和 \(F\) 一样的递推方式进行递推,每次从 \(i-1\) 到 \(i\) ,就乘 \(d=A_i-A_{i-1}\) 次转移矩阵,算出dp值后再把当前 \(i\) 加到 \(V\) 里即可,最后输出 \(ans=dp_{n+1}\) 。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
const int Mod=998244353;
const int N=1e5+5;
int n;
ll S;
ll A[N];
inline void add(int &x,int y){
    x+=y;
    if(x>=Mod) x-=Mod;
}
struct Matrix{
    int a[2][2];
    Matrix operator *(const Matrix &B)const{
        Matrix res={};
        for(int i=0;i<2;i++){
            for(int j=0;j<2;j++){
                for(int k=0;k<2;k++){
                    add(res.a[i][j],(ll)a[i][k]*B.a[k][j]%Mod);
                }
            }
        }
        return res;
    }
}init,p,V;
inline Matrix ksm(Matrix x,ll y){
    Matrix res={};
    res.a[0][0]=res.a[1][1]=1;
    while(y){
        if(y&1) res=res*x;
        y>>=1;
        x=x*x;
    }
    return res;
}
inline int fb(ll x){
    if(x==0) return 0;
    if(x==-1) return 1;
    return (init*ksm(p,x-1)).a[0][1];
}
ll dp[N];
int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n>>S;
    for(int i=1;i<=n;i++) cin>>A[i];
    A[++n]=S;
    init.a[0][1]=1;
    p.a[0][1]=p.a[1][0]=p.a[1][1]=1;
    dp[1]=fb(A[1]);
    V.a[0][0]=dp[1];
    for(int i=2;i<=n;i++){
        V=V*ksm(p,A[i]-A[i-1]);
        dp[i]=(fb(A[i])-V.a[0][1]+Mod)%Mod;
        add(V.a[0][0],dp[i]);
    }
    cout<<dp[n]<<'\n';
    return 0;
}
posted @ 2026-10-08 16:04  bjq521  阅读(3)  评论(0)    收藏  举报