数学知识——高斯消元法和容斥原理

高斯消元法

定义原理
  1. 内容
    消元法是将方程组中的一方程的未知数用含有另一未知数的代数式表示,并将其代入到另一方程中,这就消去了一未知数,得到一解;或将方程组中的一方程倍乘某个常数加到另外一方程中去,也可达到消去一未知数的目的。消元法主要用于二元一次方程组的求解。

  2. 核心
    1)两方程互换,解不变;
    2)一方程乘以非零数k,解不变;
    3)一方程乘以数k加上另一方程,解不变 。

  3. 举例介绍

    转化为行列式
    在这里插入图片描述
    由行列式求解在这里插入图片描述

    其中计算过程可能有误,但大体流程是对的

  4. 总结方法
    1)转换行列式

    1. 枚举1~n列,假设当前列为第i列,找到第i列第i行到n行最大的数,将其所在行挪到第i行
    2. 将第i行乘一个非0数使得第i行第i列元素变为1,然后用第i行与下面所有行进行运算,使下面所有行的第i列元素变为0

    2)行列式求解
    从第n行开始枚举到第1行假设为第i行,每一行的第i列到第n列,假设为j列都由第j行的相应的首位非0数消为0,最终得到的第n + 1列即为解

例题

输入一个包含 n 个方程 n 个未知数的线性方程组。

方程组中的系数为实数。

求解这个方程组。

下图为一个包含 m 个方程 n 个未知数的线性方程组示例:

在这里插入图片描述

输入格式
第一行包含整数 n。

接下来 n 行,每行包含 n+1 个实数,表示一个方程的 n 个系数以及等号右侧的常数。

输出格式
如果给定线性方程组存在唯一解,则输出共 n 行,其中第 i 行输出第 i 个未知数的解,结果保留两位小数。

如果给定线性方程组存在无数解,则输出 Infinite group solutions。

如果给定线性方程组无解,则输出 No solution。

数据范围
1≤n≤100,
所有输入系数以及常数均保留两位小数,绝对值均不超过 100。

输入样例:
3
1.00 2.00 -1.00 -6.00
2.00 1.00 -3.00 -9.00
-1.00 -1.00 2.00 7.00
输出样例:
1.00
-2.00
3.00

n = int(input())
eps = 1e-8
p = []

def gauss() :
	r = 0
	for c in range(n) :
		t = r
		for i in range(t + 1, n) :
			if p[t][c] < p[i][c] :
				t = i
		if abs(p[t][c]) < eps :
			continue
		for i in range(c, n + 1) :
			p[t][i], p[r][i] = p[r][i], p[t][i]
		for i in range(n, c - 1, -1) :
			p[r][i] /= p[r][c]
		for i in range(r + 1, n) :
			if abs(p[i][c]) < eps :
				continue
			for j in range(n, c - 1, -1) :
				p[i][j] -= p[r][j] * p[i][c]
		r += 1
	if r < n :
        for i in range(r, n) :
            if (abs(p[i][n]) > eps) :
                return 2
        return 1
    
    for i in range(n - 1, -1, -1) :
        for j in range(i + 1, n) :###对于第i行的i列不需要被消,其余都要被消
            p[i][n] -= p[i][j] * p[j][n]
    return 0

for i in range(n) :
	p.append(list(map(int, input().split())))
t = gauss()
if t == 1 :
	print("Infinite group solutions")
elif t == 2 :
	print("No solution")
else :
	for i in range(n) :
        if abs(p[i][n]) <= 0 :
            p[i][n] = 0
        print("%.2f"%p[i][n])

容斥原理

简介

在计数时,必须注意没有重复,没有遗漏。为了使重叠部分不被重复计算,人们研究出一种新的计数方法,这种方法的基本思想是:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。

公式

在这里插入图片描述

例题

给定一个整数 n 和 m 个不同的质数 p1,p2,…,pm。

请你求出 1∼n 中能被 p1,p2,…,pm 中的至少一个数整除的整数有多少个。

输入格式
第一行包含整数 n 和 m。

第二行包含 m 个质数。

输出格式
输出一个整数,表示满足条件的整数的个数。

数据范围
1≤m≤16,
1≤n,pi≤10^9
输入样例:
10 2
2 3
输出样例:
7

n, m = map(int, input().split())

p = list(map(int, input().split()))

res = 0

for i in range(1, 1 << m) :
	t = 1
	s = 0
	for j in range(m) :
		if i >> j & 1 :
			if t * p[j] > n :
				t = -1
				break
			t *= p[j]
			s += 1
	if t != -1 :
		if s % 2 :
			res += n // t
		else :
			res -= n // t
print(res)

对于枚举1~2^m的组合数,可以用m二进制来枚举,学到了。1移m位,然后枚举1 ~ 2^m中所有数,每一位可以用1~m移位来求

总结

数学知识告一段落,数学果然烧脑子

posted @   chanxe  阅读(203)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示