OI模板 高斯消元/线性基

OI模板 高斯消元

高斯消元

//P3389
#include <bits/stdc++.h>
using namespace std;

const int N = 110;
const double eps = 1e-4;
double a[N][N];
int n;

int gauss(){
	int c, r;
	for(c = 1, r = 1; c <= n; ++ c){
		int tmp = r;
		for(int i = r; i <= n; ++ i){
			if(fabs(a[i][c]) > fabs(a[tmp][c])){
				tmp = i;
			}
		}
		if(fabs(a[tmp][c]) < eps){
			continue;
		}
		swap(a[tmp], a[r]);
		double val = a[r][c];
		for(int i = 1; i <= n+1; ++ i){
			a[r][i] /= val;
		}
		for(int i = 1; i <= n; ++ i){
		    if(i == r) continue;
		    val = a[i][c];
			for(int j = 1; j <= n+1; ++ j){
				a[i][j] -= a[r][j] * val;
			}
		}
		++ r;
	}
	if(r <= n){
		for(int i = r; i <= n; ++ i){
			if(fabs(a[i][n+1]) > eps){
				return 2;// no solution
			}
		}
		return 1;//inf
	}
	return 0;
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n; ++ i){
		for(int j = 1; j <= n + 1; ++ j){
			scanf("%lf", &a[i][j]);
		}
	}
	if(gauss()){
		puts("No Solution");
		return 0;
	}
	for(int i = 1; i <= n; ++ i){
		printf("%.2lf\n", a[i][n+1]);
	}
	return 0;
}

矩阵求逆

设求 A A A 矩阵的逆,则在高斯消元把 A A A 矩阵通过初等行变换转换为单位矩阵时,对另一个单位矩阵 B B B 进行相同的操作,最后的 B B B 即为 A A A 的逆矩阵。

//P4783
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int N = 410;
const ll P = 1e9 + 7;
int n;
ll a[N][N], b[N][N];
 
ll qp(ll a, ll b){
    ll ans = 1;
    while(b){
        if(b & 1){
            ans = ans * a % P;
        }
        a = a * a % P;
        b >>= 1;
    }
    return ans;
}
 
ll inv(ll x){
    return qp(x, P-2);
}
 
int gauss(){
    int c, r;
    ll val;
    for(c = 1, r = 1; c <= n; ++ c){
        int tmp = r;
        for(int i = r; i <= n; ++ i){
            if(a[i][c]){
                tmp = i;
            }
        }
        if(!a[tmp][c]){
            continue;
        }
        swap(a[tmp], a[r]);
        swap(b[tmp], b[r]);
        val = inv(a[r][c]);
        for(int i = 1; i <= n; ++ i){
            a[r][i] = a[r][i] * val % P;
            b[r][i] = b[r][i] * val % P;
        }
        for(int i = 1; i <= n; ++ i){
            if(i == r) continue;
            val = a[i][c];
            for(int j = 1; j <= n; ++ j){
                a[i][j] = (a[i][j] - a[r][j] * val % P + P) % P;
                b[i][j] = (b[i][j] - b[r][j] * val % P + P) % P;
            }
        }
        ++ r;
    }
    return r <= n;
}
 
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= n; ++ j){
            scanf("%lld", &a[i][j]);
            if(i == j){
                b[i][j] = 1;
            }
        }
    }
    if(gauss()){
        puts("No Solution");
        return 0;
    }
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= n; ++ j){
            printf("%lld ", b[i][j]);
        }
        puts("");
    }
    return 0;
}

行列式求值

//P7112
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 610;
int n;
ll a[N][N], p;

ll calc(){
	ll res = 1, w = 1;
	for(int i = 1; i <= n; ++ i){
		for(int j = i + 1; j <= n; ++ j){
			while(a[i][i]){
				ll div = a[j][i] / a[i][i];
				for(int k = i; k <= n; ++ k){
					a[j][k] = (a[j][k] - div * a[i][k] % p + p) % p;
				}
				swap(a[i], a[j]), w = -w;
			}
			swap(a[i], a[j]), w = -w;
		}
	}
	res = w;
	for(int i = 1; i <= n; ++ i){
		res = res * a[i][i] % p;
	}
	return (res + p) % p;
}

void solve(){
	scanf("%d%lld", &n, &p);
	for(int i = 1; i <= n; ++ i){
		for(int j = 1; j <= n; ++ j){
			scanf("%d", &a[i][j]);
		}
	}
	printf("%lld\n", calc());





}

int main(){
	solve();
	return 0;
}

//qwq


线性基

const int N = 63;
struct LinearBasis{
	ll p[N+10], b[N+10];
	int tot = 0, flg_zero = 0;
	void ins(ll x){
		for(int i = N; i >= 0; -- i){
			if(x & (1ll << i)){
				if(!p[i]){
					p[i] = x;
					return;
				}
				x ^= p[i];
			}
		}
		flg_zero = 1;
		return; 
	}
	ll getmx(){
		ll ans = 0;
		for(int i = N; i >= 0; -- i){
			ans = max(ans, ans ^ p[i]);
		}
		return ans;
	}
	ll getmn(){
		if(flg_zero){
			return 0;
		}
		for(int i = 0; i <= N; ++ i){
			if(p[i]){
				return p[i];
			}
		}
	}
	bool isin(ll x){
		for(int i = N; i >= 0; -- i){
			if(x & (1ll << i)){
				x ^= p[i];
			}
		}
		return x ? 0 : 1;
	}
	void rebuild(){
		tot = 0;
		for(int i = 0; i <= N; ++ i){
			if(p[i]){
				for(int j = i - 1; j >= 0; -- j){
					if(p[j] && (p[i] & (1ll << j))){
						p[i] ^= p[j];
					}
				}
				b[tot++] = p[i];
			}
		}
	}
	ll kthmn(ll k){
		k -= flg_zero;
		if(!k){
			return 0;
		}
		ll ans = 0;
		if(k >= (1ll<<tot)){
			return -1;
		}
		for(int i = 0; i <= N; ++ i){
			if(k & (1ll<<i)){
				ans ^= b[i];
			}
		}
		return ans;
	}
} b;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值