ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[dp 记录] abc258Ex Odd Steps

2022-07-08 08:32:26  阅读:130  来源: 互联网

标签:matrix int list ++ abc258Ex Steps include Odd dp


题意转化:给定 \(n\) 个整数和 \(S\),选一个从小到大排序的数列,\(0\) 和 \(S\) 必选,使相邻两数奇偶性不同,给出的 \(n\) 个数不能选。求方案数。
\(S \leq 10^{18},n \leq 10^5\)

看着非常 \(dp\),但是 \(S\) 极大,于是就是矩乘优化 \(dp\) 了。

令 \(dp_i\) 表示所选数均 \(\leq i\) 的情况,但又需要知道奇偶性以转移,于是 \(dp_{i,0/1}\) 表示所选数最大为 \(i\),所选最大数膜 \(2\) 余数为 \(i+0/1\) 的情况。此时,我们要求的是 \(dp_{i-1,0}\),因为最后还要选 \(S\) 出来。这样转化,我们看着丢失了直接获得答案的能力,但与此相比,我们可以以 \(O(1)\) 而非 \(O(n)\) 的代价递推,并仍能通过 \(O(1)\) 的代价获得答案。

\[\left\{ \begin{array}{ll} dp_{i,0} & \gets & dp_{i-1,1} + dp_{i-1, 0} \cdot [\text{if i could be chosen}] \\ dp_{i,1} & \gets & dp_{i-1,0} \end{array} \right. \]

将 \(n\) 个 \(a_i\) 作为分界,两个 \(a_i\) 之间用矩乘转移,否则朴素转移,即得。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <initializer_list>
#define LL long long
using namespace std;
const int M = 100005, mod = 998244353;
struct matrix{
    int a[2][2], n, m;
    matrix() {}
    matrix(int n_, int m_) {n = n_; m = m_; memset(a, 0, sizeof(a));}
    matrix(int n_) {
        n = m = n_; memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i++) a[i][i] = 1;
    }
    matrix(initializer_list<initializer_list<int>> list){
        n = list.size(); int l = 0;
        for(auto i : list){
            int v = 0; m = i.size();
            for(auto j : i) a[l][v++] = j;
            ++l; 
        }
    }
    int* operator [] (int i){
        return a[i];
    }
    matrix operator * (const matrix &tmp) {
        matrix t(n, tmp.m);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < t.m; j++)
                for(int k = 0; k < m; k++)
                    t[i][j] = (t[i][j] + 1ll * a[i][k] * tmp.a[k][j] % mod) % mod;
        return t;
    }
    void print(string s){
        cout << s << ":\n";
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++) printf("%d ", a[i][j]);
            printf("\n");
        }
    }
};
matrix qpow(matrix a, LL b){
    matrix ans(a.n);
    for(; b; b >>= 1){
        if(b & 1) ans = ans * a;
        a = a * a;
    }
    return ans;
}
int n; LL s, a[M];
int main(){
    scanf("%d %lld", &n, &s);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
    matrix dp({{1, 0}}); matrix t({{1, 1}, {1, 0}});
    for(int i = 1; i <= n; i++){
        matrix x = dp * qpow(t, a[i] - a[i-1] - 1);
        dp[0][1] = x[0][0]; dp[0][0] = x[0][1];
    }
    dp = dp * qpow(t, s - a[n] - 1);
    printf("%d\n", dp[0][0]);
}

标签:matrix,int,list,++,abc258Ex,Steps,include,Odd,dp
来源: https://www.cnblogs.com/purplevine/p/16456910.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有