1 条题解

  • 0
    @ 2025-10-26 16:16:47
    #include <iostream>
    #define ll long long
    using namespace std;
    const ll md = 1000000007;
    inline ll qp(ll x, ll y) {
        ll rt = 1;
    
        for (; y; y >>= 1, (x *= x) %= md)
            if (y & 1)
                (rt *= x) %= md;
    
        return rt;
    }
    int main() {
        int n, m;
        cin >> n >> m;
    
        if (n > m)
            swap(n, m);
    
        if (n == 1)
            cout << qp(2, m);
    
        if (n == 2)
            cout << 4 * qp(3, m - 1) % md;
    
        if (n == 3)
            cout << 112 * qp(3, m - 3) % md;
    
        if (n > 3) {
            if (n == m)
                cout << (83 * qp(8, n) + 5 * qp(2, n + 7)) % md * 190104168 % md;
            else
                cout << (83 * qp(8, n) % md + qp(2, n + 8))*qp(3, m - n - 1) % md * 570312504 % md;
        }
    }
    
    

    算法标签

    • 快速幂快速幂
    • 分类讨论分类讨论
    • 数学公式数学公式
    • 模运算模运算

    问题核心

    给定 n×mn\times m 的棋盘,每个格子填 0011,满足约束:若路径移动字符串 w(P1)>w(P2)w(P_1) > w(P_2)(字典序),则数字字符串 s(P1)s(P2)s(P_1) \le s(P_2)(字典序)。求合法填法数,答案对 109+710^9+7 取模。

    核心思路

    1. 行列对称:交换 nnmm 使 nmn\le m,填法数不变,简化讨论。
    2. 分类计算:按 nn 的取值套用预推导公式,大指数通过快速幂高效求解。
    3. 模运算保障:所有运算后取模 109+710^9+7,逆元预存为常量,避免除法溢出。

    核心分类公式(nmn\le m

    nn 取值 场景 计算公式
    11 单行棋盘 2mmod109+72^m \mod 10^9+7
    22 两行棋盘 4×3m1mod109+74 \times 3^{m-1} \mod 10^9+7
    33 三行棋盘 112×3m3mod109+7112 \times 3^{m-3} \mod 10^9+7
    n>3n>3 正方形(n=mn=m $(83 \times 8^n + 5 \times 2^{n+7}) \times 190104168 \mod 10^9+7$
    长方形(n<mn<m $(83 \times 8^n + 2^{n+8}) \times 3^{m-n-1} \times 570312504 \mod 10^9+7$

    代码关键

    • 快速幂(qp):O(logy)O(\log y) 计算大指数幂,避免超时。
    • 模运算:所有乘法后取模,防止数值溢出。
    • 逆元常量:190104168190104168570312504570312504 是模意义下除法的转化系数。

    复杂度

    • 时间:O(logmax(n,m))O(\log \max(n,m))(仅快速幂开销)
    • 空间:O(1)O(1)(仅用常量级变量)
    • 1

    信息

    ID
    4186
    时间
    2000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者