2020牛客暑期多校训练营(第一场)D-Quadratic Form

题目链接:https://ac.nowcoder.com/acm/contest/5666/B
Bobo has a positive-definite n \times nn×n matrix AA and an nn-dimension vector bb…
题意:
在这里插入图片描述
对于所给矩阵A和向量b,找到一个x使得满足上述约束条件下,bixi求和最大,且求这个值的平方和。

思路:这是一个数学题,赛后在群里看到有大佬发了证明过程,由于不是本人所写也只是大概看懂不能自己推导,所以在此不完全贴出,核心过程是对w(x)进行矩阵的变换,得到|w(x)| = |(A-1b)TAX|,利用柯西施瓦茨不等式放缩得
|w(x)|<=sqrt(bTA-1b)
所以原式最大值就是bTA-1b
自己写了一遍大概是这样,问号的地方没懂为什么可以这么假设,感觉是高代里面的一个知识。好像是正定矩阵的某种特性。
在这里插入图片描述
但还是把这题补了,主要是之前没做过矩阵求逆的题目。
注意,输入的坑可能为负数。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int maxn = 2e2 + 5;
ll a[maxn][maxn];
ll n, is[maxn], js[maxn];
void exgcd(ll a, ll b, ll& x, ll& y) {
    
    
    if (!b)return x = 1, y = 0, void();
    exgcd(b, a % b, y, x); y -= x * (a / b);
}
ll inv(int p) {
    
    
    ll x, y; exgcd(p, mod, x, y);
    return (x + mod) % mod;
}
void inv() {
    
    
    for (int k = 1; k <= n; k++) {
    
    
        for (int i = k; i <= n; i++) {
    
    
            for (int j = k; j <= n; j++) {
    
    
                if (a[i][j]) {
    
    
                    is[k] = i, js[k] = j; break;
                }
            }
        }

        for (int i = 1; i <= n; i++)
            swap(a[k][i], a[is[k]][i]);

        for (int i = 1; i <= n; i++)
            swap(a[i][k], a[i][js[k]]);

        if (!a[k][k]) {
    
    
            puts("No Solution");
            exit(0);
        }

        a[k][k] = inv(a[k][k]);
        for (int j = 1; j <= n; j++) {
    
    
            if (j != k) {
    
    
                (a[k][j] *= a[k][k]) %= mod;
            }
        }

        for (int i = 1; i <= n; i++) {
    
    
            if (i != k) {
    
    
                for (int j = 1; j <= n; j++) {
    
    
                    if (j != k) {
    
    
                        (a[i][j] += mod - a[i][k] * a[k][j] % mod) %= mod;
                    }
                }
            }
        }

        for (int i = 1; i <= n; i++) {
    
    
            if (i != k) {
    
    
                a[i][k] = (mod - a[i][k] * a[k][k] % mod) % mod;
            }
        }
    }
    for (int k = n; k; k--) {
    
    
        for (int i = 1; i <= n; i++) swap(a[js[k]][i], a[k][i]);
        for (int i = 1; i <= n; i++) swap(a[i][is[k]], a[i][k]);
    }
}
ll b[maxn];
ll c[maxn];

int main() {
    
    
    while (scanf("%d", &n) == 1) {
    
    
        memset(a, 0, sizeof(a));
        memset(b, 0, sizeof(b));
        memset(is, 0, sizeof(is));
        memset(js, 0, sizeof(js));
        memset(c, 0, sizeof(c));
        for (int i = 1; i <= n; i++) {
    
    
            for (int j = 1; j <= n; j++) {
    
    
                scanf("%lld", &a[i][j]);

                while (a[i][j] < 0) a[i][j] += mod;
            }
        }

        inv();

        for (int i = 1; i <= n; i++) scanf("%lld", &b[i]);

        ll ans = 0;

        for (int i = 1; i <= n; i++) {
    
    
            for (int j = 1; j <= n; j++) {
    
    
                c[i] += (ll)a[i][j] * b[j];
                c[i] %= mod;
            }
            ans += c[i] * b[i];
            ans %= mod;
        }

        printf("%lld\n", ans);
    }

    return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_43269437/article/details/107374146
今日推荐