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;
}