2020牛客暑期多校训练营(第一场)D
Quadratic Form
https://ac.nowcoder.com/acm/contest/5666/D
D. Quadratic Form
题目描述
Bobo has a positive-definite matrix
and an
-dimension vector
. He would like to find
where
,
and
is maximum.
It can be shown that , which is rational.
Find the value of .
输入描述
The input consists of several test cases terminated by end-of-file.
The first line of each test case contains an integer .
The -th of the following
lines contains
integers
.
The last line contains integers
.
,
,
.
, for any
.
.
The sum of does not exceed
.
输出描述
For each test case, print an integer which denotes the result.
示例1
输入
2
1 0
0 1
0 0
2
1 0
0 1
1 1
2
8 4
4 3
1 1
输出
0
2
623902721
分析
将题目转化为约束条件下的最值问题。此处只讨论极值,不讨论边界可能存在的最值。
考虑到约束条件 为不等式约束,可以添加
条件,利用拉格朗日乘数法求解。
首先需要讨论矩阵 的一些性质。由于
,故
可逆。根据
且
,得
为实对称矩阵,继而
也为实对称矩阵。又有
,故
为正定矩阵,继而
也为正定矩阵。上述性质都会在接下来的推导中涉及。
定义:,
。 则有约束条件
,要求最大值的表达式为
或
。
令 ;有
方程组如下。
将 方程组的第一式展开,得到如下方程组。
将上述方程组写成矩阵形式,有 。即
,等式两边取转置,得
;
,得
。代入约束条件,移项后有
,
;由于
为正定矩阵,故
;所以约束条件是有效的,即
。根据式
,可得到最优解为
;将其带入式
,有
。
由于 ,代入最优解
,得
的最大值为
。于是,
最大值为
;将式
代入,有
。
综上所述,最终答案为 。套用矩阵求逆模板和矩阵乘法公式即可。
代码
/******************************************************************
Copyright: 11D_Beyonder All Rights Reserved
Author: 11D_Beyonder
Problem ID: 2020牛客暑期多校训练营(第一场) Problem D
Date: 7/22/2020
Description:
Use lagrange multiplier method
Compute the inverse matrix
*******************************************************************/
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=202;
const ll mod=998244353;
ll a[N][N<<1],b[N],c[N];
int n;
void inverse();
ll qpow_mod(ll a,int b);
int main()
{
while(~scanf("%d",&n))
{
int i,j,k;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
scanf("%lld",&a[i][j]);
a[i][n+j]=0;//初始化
a[i][j]%=mod;
}
}
for(i=1;i<=n;i++)
{
scanf("%lld",b+i);
b[i]%=mod;
}
inverse();
//=========================================
//a[1][1+n]*b[1]+a[2][1+n]*b[2]...
//a[2][1+n]*b[1]+a[2][1+n]*b[2]...
//...
for(j=1;j<=n;j++)
{
ll res=0;
for(i=1;i<=n;i++)
{
res+=a[i][j+n]*b[i];
res%=mod;
}
c[j]=res%mod;
}
//c存b的转置由乘A的结果
//==========================================
//计算c右乘B
ll ans=0;
for(i=1;i<=n;i++)
{
ans+=b[i]*c[i];
ans%=mod;
}
//==========================================
printf("%lld\n",ans);
}
return 0;
}
void inverse()//矩阵求逆模板
{
int m=n+n;
int i,j,k;
for(i=1;i<=n;i++) a[i][i+n]=1;
for(i=1;i<=n;i++)
{
for(j=i;j<=n;j++)
{
if(a[j][i])
{
for(k=1;k<=m;k++)
{
swap(a[i][k],a[j][k]);
}
}
}
ll r=qpow_mod(a[i][i],mod-2);
for(j=i;j<=m;j++) a[i][j]=r*a[i][j]%mod;
for(j=1;j<=n;j++)
{
if(i==j) continue;
ll rate=a[j][i]*a[i][i]%mod;
for(k=i;k<=m;k++)
{
a[j][k]=a[j][k]-rate*a[i][k]%mod;
a[j][k]=(a[j][k]%mod+mod)%mod;
}
}
}
}
ll qpow_mod(ll a,int b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
} 收集牛客暑期多校训练营的题解
