Martian148's blog Martian148's blog
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档

Martian148

一只热爱文科的理科生
首页
  • ICPC 算法笔记
  • ICPC 算法题解
  • 体系结构
  • 高等数学
  • 线性代数
  • 概率论与数理统计
  • 具体数学
  • Martian148的奇思妙想
  • 游记
  • 通识课笔记
关于
  • useful 网站
  • 友情链接
  • 分类
  • 归档
  • codeforses 题解

  • atcoder 题解

  • XCPC 题解

  • 校训练赛题解

  • 牛客题解

  • 蓝桥杯题解

  • 典题选讲

    • CF2025E Card Game (动态规划、多项式快速幂、银牌题)
    • CF2026E Best Subsequence(网络流、最大权闭合图,铜牌题)
    • 牛客多校6 C Stack(数论,第一类斯特林数,铜牌题)
    • ICPC2025Online2 E Zero
    • 算法题解
    • 典题选讲
    martian148
    2025-09-18
    目录

    ICPC2025Online2 E Zero

    # ICPC2025Online2 E Zero

    ICPC2025Online2 E Zero (opens new window)

    # Solution

    设 fnf_nfn​ 表示长度为 nnn 的序列,值域为 2M2^M2M 的答案

    我们能构造如下递推柿子

    第一行随便放,方案为 2M2^M2M,第二行到第 n−1n-1n−1 行,不能和上一行一样,方案数为 2M−12^M-12M−1

    以及放了 n−1n-1n−1 行,最后一行就已经确定了

    但是此时有可能最后一行和最后一行一样,我们需要减掉这样的方案,由于最后两位的异或为 0,所以要减去 (2M−1)fn−2(2^M-1)f_{n-2}(2M−1)fn−2​,于是得到递推式

    fn=2M(2M−1)n−2−(2M−1)fn−2 f_n=2^M(2^M-1)^{n-2}-(2^M-1)f_{n-2} fn​=2M(2M−1)n−2−(2M−1)fn−2​

    这个东西是线性的,于是可以用矩阵快速幂来求解,但不是常系数的,所以需要增加一维记录 (2M−1)n(2^{M}-1)^n(2M−1)n

    [fnfn−2(2M−1)n]=[−(2M−1)02M10000(2M−1)2][fn−2fn−4(2M−1)n−2] \left[\begin{array}{c} f_{n} \\ f_{n-2} \\ \left(2^{M}-1\right)^{n} \end{array}\right] = \left[\begin{array}{ccc} -\left(2^{M}-1\right) & 0 & 2^{M} \\ 1 & 0 & 0 \\ 0 & 0 & \left(2^{M}-1\right)^{2} \end{array}\right]\left[\begin{array}{c} f_{n-2} \\ f_{n-4} \\ \left(2^{M}-1\right)^{n-2} \end{array}\right] ⎣⎢⎡​fn​fn−2​(2M−1)n​⎦⎥⎤​=⎣⎢⎡​−(2M−1)10​000​2M0(2M−1)2​⎦⎥⎤​⎣⎢⎡​fn−2​fn−4​(2M−1)n−2​⎦⎥⎤​

    分奇偶快速幂就好了

    #include <bits/stdc++.h>
    using namespace std;
    
    using i64 = long long;
    constexpr int P = 998244353;
    
    int norm(int x) {
        if (x < 0) {
            x += P;
        }
        if (x >= P) {
            x -= P;
        }
        return x;
    }
    
    template<class T>
    T power(T a, i64 b) {
        T res = 1;
        for (; b; b /= 2, a *= a) {
            if (b % 2) {
                res *= a;
            }
        }
        return res;
    }
    
    struct Z {
        int x;
        Z (int x = 0) : x(norm(x)) {}
        int val() const {
            return x;
        }
        Z operator - () const {
            return Z(norm(P - x));
        }
        Z inv() const {
            // assert(x != 0);
            if (x == 0) {
                return 1;
            }
            return power(*this, P - 2);
        }
        Z &operator *= (const Z &rhs) {
            x = i64(x) * rhs.x % P;
            return *this;
        }
        Z &operator += (const Z &rhs) {
            x = norm(x + rhs.x);
            return *this;
        }
        Z &operator -= (const Z &rhs) {
            x = norm(x - rhs.x);
            return *this;
        }
        Z &operator /= (const Z &rhs) {
            return *this *= rhs.inv();
        }
        friend Z operator * (const Z &lhs, const Z &rhs) {
            Z res = lhs;
            res *= rhs;
            return res;
        }
        friend Z operator + (const Z &lhs, const Z &rhs) {
            Z res = lhs;
            res += rhs;
            return res;
        }
        friend Z operator - (const Z &lhs, const Z &rhs) {
            Z res = lhs;
            res -= rhs;
            return res;
        }
        friend Z operator / (const Z &lhs, const Z &rhs) {
            Z res = lhs;
            res /= rhs;
            return res;
        }
        friend std::istream &operator >> (std::istream &is, Z &a) {
            i64 v;
            is >> v;
            a = Z(v);
            return is;
        }
        friend std::ostream &operator << (std::ostream &os, const Z &a) {
            return os << a.val();
        }
    };
    
    struct Matrix : array<array<Z, 3>, 3> {
        Matrix() {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    (*this)[i][j] = Z(0);
                }
            }
        }
    
        friend Matrix operator * (const Matrix &a, const Matrix &b) {
            Matrix res;
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    for (int k = 0; k < 3; k++) {
                        res[i][j] += a[i][k] * b[k][j];
                    }
                }
            }
            return res;
        }
    };
    
    Matrix qpow(Matrix a, i64 b) {
        Matrix res = Matrix();
        for (int i = 0; i < 3; i++)
            res[i][i] = 1;
        while (b) {
            if (b & 1) { res = res * a; }
            a = a * a;
            b = b >> 1;
        }
        return res;
    }
    
    void solve() {
        i64 n, m; cin >> n >> m;
        if (n == 1) {
            cout << 1 << '\n';
            return ;
        }
    
        Z g = power(Z(2), m) - Z(1);
    
        Matrix A;
        A[0][0] = -g; A[0][2] = g + 1; A[1][0] = 1; A[2][2] = g * g;
    
        Matrix a0;
        i64 exp;
        if (n % 2 == 0) {
            a0[0][0] = 0;
            a0[1][0] = 0;
            a0[2][0] = g * g;
            exp = (n - 2) / 2;
        }
        else {
            a0[0][0] = g * g;
            a0[1][1] = 0;
            a0[2][0] = g * g * g;
            exp = (n - 3) / 2;
        }
    
        Matrix ans = qpow(A, exp) * a0;
        cout << ans[0][0] << '\n';
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);  cin.tie(nullptr);
    
        int t; cin >> t;
        while (t--) {solve();}
    
        return 0;
    }
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    牛客多校6 C Stack(数论,第一类斯特林数,铜牌题)

    ← 牛客多校6 C Stack(数论,第一类斯特林数,铜牌题)

    最近更新
    01
    打破信息差,一条学校不教的计算机学习之路
    09-18
    02
    模型与分词器
    09-17
    03
    大二总结
    09-03
    更多文章>
    Theme by Vdoing | Copyright © 2024-2025 Martian148 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式