矩阵离奇的负数

P11362 [NOIP2024] 遗失的赋值

kmguochang @ 2024-12-16 19:51:55

我用的是矩阵加速优化DP,但是官方第二组数据就出现了离奇的负数

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9 + 7;
map<int, int> mp;
int n, m, v;
struct Mat {
    ll a[3][3];
    Mat() {
        memset(a, 0, sizeof(a));
    }
    Mat operator*(const Mat &b)const {
        Mat res;
        for (int i = 1; i < 3; ++i)
            for (int j = 1; j < 3; ++j)
                for (int k = 1; k < 3; ++k)
                    res.a[i][j] = (res.a[i][j] + (a[i][k] % mod) * (b.a[k][j] % mod) % mod) % mod;//这里如果不在每个元素后加mod的话就会爆long long(屏幕输出调出来的)
        /*printf("\n");
        for (int i = 1; i < 3; ++i) {
            for (int j = 1; j < 3; ++j)
                printf("%lld ", a[i][j]);
            printf("\n");
        }
        for (int i = 1; i < 3; ++i) {
            for (int j = 1; j < 3; ++j)
                printf("%lld ", b.a[i][j]);
            printf("\n");
        }
        for (int i = 1; i < 3; ++i) {
            for (int j = 1; j < 3; ++j)
                printf("%lld ", res.a[i][j]);
            printf("\n");
        }*/
        return res;
    }
} basx, basy, ans, bas_y;
void mulx(int t) {
    bas_y = basy;
    while (t > 0) {
        if (t & 1)
            ans = ans * bas_y;
        bas_y = bas_y * bas_y;
        t >>= 1;
    }
    return;
}
int main() {
    freopen("assign2.in", "r", stdin);
    freopen("1.out", "w", stdout);
    int T, x, y, lst;
    bool vis;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d%d", &n, &m, &v);
        mp.clear();
        vis = true;
        for (int i = 1; i <= m; ++i) {
            scanf("%d%d", &x, &y);
            if (mp[x] && mp[x] != y)
                vis = false;
            mp[x] = y;
        }
        if (!vis) {
            printf("0\n");
            continue;
        }
        if (mp[1])
            ans.a[1][1] = 0ll, ans.a[1][2] = 1ll;
        else
            ans.a[1][1] = 1ll, ans.a[1][2] = 0ll;
        basx.a[1][2] = 1ll * v * v, basx.a[2][2] = 1ll * v * (v - 1) + 1ll;
        basy.a[1][1] = 1ll * v * v, basy.a[2][1] = 1ll * v * (v - 1), basy.a[2][2] = 1ll * v;
        lst = 1;
        for (auto to : mp) {
            x = to.first;
            if (x == 1)
                continue;
            mulx(x - lst - 1);
            lst = x;
            ans = ans * basx;
        }
        mulx(n - lst);
        printf("%lld\n", (ans.a[1][1] + ans.a[1][2]) % mod);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

我感觉每个矩阵都是取过模的,不知道为什么会有很大的数字来撑爆long longQAQ


by A_chicken_boy @ 2024-12-17 18:55:37

emm... 你的mulx函数取模了吗?


by A_chicken_boy @ 2024-12-17 18:55:52

@kmguochang


by mutianhanhan @ 2024-12-17 19:06:17

@kmguochang 可爱捏


by kmguochang @ 2024-12-17 19:16:09

@A_chicken_boy

取模是在矩阵乘法里面的

代码有注释,可能太长被隐蔽了

res.a[i][j] = (res.a[i][j] + (a[i][k] % mod) * (b.a[k][j] % mod) % mod) % mod;
//这里如果不在每个元素后加mod的话就会爆long long(屏幕输出调出来的)

by kmguochang @ 2024-12-17 19:20:26

原版是这样的

实测矩阵里面会出现超过1e9+7的数字撑爆long long

res.a[i][j] = (res.a[i][j] + a[i][k] * b.a[k][j] % mod) % mod;

|