题目链接: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;
}