模板:线性代数

16 篇文章 1 订阅

线性基

异或线性基

若要查询第k小子集异或和,则把k写成二进制,对于是1的第i位,把从低位到高位第i个不为0的数异或进答案。若要判断是否有非空子集的异或和为0,如果不存在自由基,那么说明只有空集的异或值为0,需要高斯消元来判断。

struct BaseXOR
{
	vector<ll> a;
	BaseXOR():a(64,0) {}
	ll ask()//查询最大子集异或和
	{
		ll t=0;
		for(int i=a.size()-1; ~i; --i)
			t=max(t,t^a[i]);
		return t;
	}
	bool add(ll x)
	{
		for(int i=a.size()-1; ~i; --i)
			if(x>>i&1)
			{
				if(a[i])x^=a[i];
				else return a[i]=x,1;
			}
		return 0;
	}
	bool check(ll x)//判断一个数是否能够被异或出,0根据需要特判
	{
		for(int i=a.size()-1; ~i; --i)
			if(x>>i&1)
				if(x^=a[i],!x)
					return 1;
		return 0;
	}
};

向量线性基

add返回要插入的向量z是否与已插入的线性无关。

struct Base
{
	vector<vector<double> > v;
	Base(int N):v(N,vector<double>(N,0)) {}//R^N的子空间
	bool add(vector<double> x)
	{
		for(int i=0; i<x.size(); ++i)
			if(fabs(x[i])>EPS)
			{
				if(fabs(v[i][i])<EPS)return v[i]=x,1;
				double t=x[i]/v[i][i];
				for(int j=0; j<x.size(); ++j)
					x[j]-=t*v[i][j];
			}
		return 0;
	}
};

矩阵

struct Matrix
{
    static int n;//方阵代替矩阵
    ll a[N][N];
    Matrix(ll k=0)
    {
        for(int i=0; i<n; ++i)fill(a[i],a[i]+n,0),a[i][i]=k;
    }
};
int Matrix::n=N;

乘法、快速幂

Matrix operator*(const Matrix &a,const Matrix &b)
{
    Matrix r(0);
    for(int i=0; i<r.n; ++i)
        for(int j=0; j<r.n; ++j)
            for(int k=0; k<r.n; ++k)
                r.a[i][j]=(r.a[i][j]+mul(a.a[i][k],b.a[k][j],M))%M;
    return r;
}
Matrix pow(Matrix a,ll b)
{
    Matrix r(1);
    for(; b; b>>=1,a=a*a)
        if(b&1)r=r*a;
    return r;
}

行列式

ll det(Matrix a)//矩阵a的n阶行列式
{
	ll ans=1;
	for(int i=0; i<a.n; ++i)
	{
		for(int j=i+1; j<a.n; ++j)
			while(fabs(a[j][i])>EPS)
			{
				ll t=a[i][i]/a[j][i];
				for(int k=i; k<n; ++k)
					a[i][k]-=t*a[j][k],swap(a[i][k],a[j][k]);
			}
		if(fabs(ans*=a[i][i])<EPS)return 0;
	}
	return ans;
}

高斯消元

struct GaussElimination:Matrix
{
	void ask()//a为增广矩阵,要求n*n的系数矩阵可逆,运行结束后a[i][n]为第i个未知数的值
	{
		for(int i=0,r; i<n; ++i)
		{
			for(int j=r=i; j<n; ++j)
				if(fabs(a[r][i])<fabs(a[j][i]))
					r=j;
			if(r!=i)swap_ranges(a[r],a[r]+n+1,a[i]);
			for(int j=n; j>=i; --j)
				for(int k=i+1; k<n; ++k)
					a[k][j]-=a[k][i]*a[i][j]/a[i][i];
		}
		for(int i=n-1; ~i; --i)
		{
			for(int j=i+1; j<n; ++j)
				a[i][n]-=a[j][n]*a[i][j];
			a[i][n]/=a[i][i];
		}
	}
};
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值