欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

2020牛客暑期多校训练营(第一场)D Quadratic Form 拉格朗日乘数法+求矩阵的逆

程序员文章站 2024-03-07 21:33:15
...

证明过程如下。

然后求个矩阵逆,矩阵乘法一下即可。

2020牛客暑期多校训练营(第一场)D	Quadratic Form 拉格朗日乘数法+求矩阵的逆



#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
const int M = 200+7;
const int mod =998244353;
ll a[M][M<<1];
ll b[M],c[M];
ll qpow(ll a,ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ans;
}
//返回*元个数,及无穷解个数 
bool Gauss(int n,int m)//对矩阵a高斯消元得到(E|C) C为等式右边的列矩阵 
{
	int row;//当前处理的行
	int col;//当前处理的列 
  	for( row=1,col=1;row<=n&&col<=n;row++,col++)
  	{
  		int mx=row;
  		for(re int i=row+1;i<=n;i++)if(abs(a[i][col])>abs(a[mx][col]))mx=i;
  		if(mx!=row)swap(a[row],a[mx]);
  		if(a[row][col]==0)//第i行一下的i列都是0 ,处理下一列 ,这种情况下会出现 无穷解或无解 
  			return -1;
  		ll inv=qpow(a[row][col],mod-2);
  		for(re int i=1;i<=n;i++)
  		{
  			 if(row==i)continue;
  			 ll tmp=a[i][col]*inv%mod;//第i行减去第row行 * tmp,消去第i行的第col列 
  			 for(int j=col;j<=m;j++)
  			 	a[i][j]=(a[i][j]-tmp*a[row][j]%mod+mod)%mod;//cout<<"----    "<<i<<" "<<j<<" "<<a[i][j]<<endl;;
		}
		for(re int j=col;j<=m;j++)a[row][j]=inv*a[row][j]%mod;
	}
	return 0;
}
int main()
{
  	int n;
  	while(~scanf("%d",&n))
	{
		memset(a,0,sizeof(a));
		memset(c,0,sizeof(c));
	  	for(re int i=1;i<=n;i++)
	  		for(int j=1;j<=n;j++)scanf("%lld",&a[i][j]);
		for(re int i=1;i<=n;i++)a[i][i+n]=1;//构造  A|E 分块矩阵 
	  	int f=Gauss(n,2*n);//分块矩阵变换 -> E|A^(-1) 
	  	for(re int i=1;i<=n;i++)scanf("%lld",&b[i]);
	  	ll ans=0;
	  	for(re int j=1;j<=n;j++)
	  		for(re int i=1;i<=n;i++)
	  			c[j]=(c[j]+a[i][j+n]*b[i]%mod+mod)%mod;//B^T * A^(-1)
	  	for(re int i=1;i<=n;i++)ans=(ans+(ll)b[i]*c[i]%mod)%mod;
	  	printf("%lld\n",(ans+mod)%mod);
	}
  	
	return 0;
}