数学总结

主要整理一下 noip csp的数学

版权声明,大部分摘抄于《信息学奥赛之数学一本通》 如有侵权行为,本文作者将删除

持续更新ing

1.1辗转相除法

辗转相除法用来求两个数的最大公约数,又称欧几里得算法,其原理是:GCD(x,y)=GCD(x,y-x);

代码实现

int GCD(int x,int y){
    if(y==0) return x;
    else return GCD(y,x%y);
}

1.2最小公倍数LCM

定理:a,b两个数的最大公约数乘以它们的最小公倍数等于两数相乘

1.3扩展欧几里得算法

用来在已知(a,b)时,求解一组(p,q),使得p * a + q * b = GCD(a,b)

根据欧几里得算法可得,a和b都在减小,当b减小到0时,就可以得出p=1,q=0.然后递归回去就可以求出最终的p和q了。

代码实现

#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

int exgcd(int a,int b,int &x,int &y){//加上&会改变下方调用x,y的值 
	int ret,tmp;
	if(!b){
		x=1;
		y=0;
		return a;
	}
	ret=exgcd(b,a%b,x,y);
	tmp=x;
	x=y;
	y=tmp-a/b*y;
	return ret;
}

int main(){
	int a,b,x,y,z;
	cin>>a>>b;
	z=exgcd(a,b,x,y);//就是这里 
	cout<<z<<" "<<x<<" "<<y<<'\n';
	return 0;
}

1.4求解线性同余方程

定理1:对于方程a * x + b * y = c,该方程等价于a * c ≡ c (mod b),有整数解的充分必要条件是: c % GCD(a,b) = 0。

根据定理1,对于方程 a * x + b * y = c,我们可以先用扩展欧几里得算法求出一组x0,y0也就是 a * x0 + b * y0 = GCD(a,b),然后两边同时除以GCD(a,b),再乘以c。这样就得到了方程 

a * x0 * c / GCD(a,b) + b * y0 * c / GCD(a,b) = c,我们也就找到了方程的一个解。

定理2:若GCD(a,b)=1,且x0,y0,为a * x+ b * y = c的一组解,则该方程的任一解可表示为:x = x0 + b * t ,y = y0 - a * t,且对任一整数t,皆成立。

根据定理2,可以求出方程的所有解。但实际问题中,我们往往被要求去求最小整数解,也就是求一个特解x,t = b / GCD(a,b),x = (x % t + t) % t。

代码实现

int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	int d=exgcd(b,a%b,x,y);
	int tmp=x;
	x=y;
	y=tmp-a/b*y;
	return d;
} //用扩展欧几里得算法求解线性方程 ax+by=c;

bool get(int a,int b,int c,int &x,int &y){
	int d=exgcd(a,b,x,y);
	if(c%d) return false;
	int k=c/d;
	x*=k;
	y*=k;
	//求的只是其中一个解 
	return true;
}

猜你喜欢

转载自www.cnblogs.com/zxjg/p/11644043.html