2020/1/17 一些数论

(不是数学课)

标签(空格分隔): 课堂笔记


最大公约数(gcd)

如果d是能同时整除a, b中最大的正整数,我们称d为a和b的最大公约数,记作d = gcd(a, b)

辗转相除法

a > b,我们有gcd(a, b) = gcd(b, a % b)

最小公倍数(lcm)

如果一个数d,既是a的倍数,又是b的倍数,同时d是满足这两个条件中的最小正整数,那么称d是a和b的最小公倍数,记作d = lcm(a, b)

gcd(a, b) * lcm(a, b) = a * b

唯一分解定理

任意一个正整数x,都可以唯一地分解成p1^a1 * p2^a2 * … * \(p_n\)^\(a_n\)的形式,其中p1到\(p_n\)是素数(不考虑素数之间的顺序)

NOIP2014 比例简化

[原题][1]
[1]: https://www.luogu.com.cn/problem/P2118
可以暴力枚举,但要注意分数,计算机在计算分数的时候会失去一定的精度。

进制

转换:P进制下的a1a2…an代表的数字是
a1 * p^(n-1) + a2 * p^(n-2) + … + an

高精度

总之就是模拟人用竖式的运算规则,进行借位,进位。
加法

struct Bignum
{
	int a[N],len;
 } 
Bignum operator+(Bignum x,Bignum y){
 	Bignum z;
 	z.len = max(x.len,y.len);
 	for(int i = 1; i <= z; i++)
 		z.a[i] = x.a[i]+y.a[i];
 	for(int i = 1; i <= z.len; i++)
 	{
 		z.a[i+1] += z.a[i]/10;
 		z.a[i] %= 10
	 }
	 if(z.a[z.len+1]>0) z.len++;
	 return z;
 }

减法


Bignum operator-(Bignum x,Bignum y)
{
	Bignum z;
	z.len=max(x.len,y.len);
	for(int i=1;i<=z.len;i++)
		z.a[i]=x.a[i]-y.a[i];
	for(int i=1;i<=z.len;i++)
	if(z.a[i]<0)
	{
		z.a[i]+=10;
		z.a[i+1]--;
	}
	while(z.a[z.len]==0)z.len--;
	return z;
}

乘法

Bignum operator*(Bignum x,Bignum y){
	Bignum z;
	z.len = x.len+y.len-1;
	for(int i = 1; i <= x.len; i++)
		for(int j = 1; j <= y; j++)
			{
				z.a[i+j-1]+=x.a[i]*y.a[i];
			}
	for(int i = 1; i <= z.len; i++){AS
		z.a[i+1] += z.a[i]/10;
		z.a[i]%=10;
	}
	while(z.a[z.len+1]>0){
		z.len++;
		z.a[z.len+1]+=z.a[z.len]/10;
		z.a[z.len]%=10;
	}
	return z;
}

除法(高精除以低精)

Bignum operator/(Bignum x,int y)
{
	Bignum z;
	z.len=x.len;
	for(int i=z.len;i;i--)
	{
		z.a[i]=x.a[i]/y;
		x.a[i-1]+=10*x.a[i]%y;
	}
	while(z.len>1&&z.a[z.len]==0)z.len--;
	return z;
}

除法(高精除以高精)

bool operator<=(Bignum x,Bignum y)
{
	if(x.len<y.len)return 1;
	if(x.len>y.len)return 0;
	for(int i=x.len;i;i--)
	if(x.a[i]!=y.a[i])
	return x.a[i]<=y.a[i];
	return 1;
}
Bignum shift(Bignum x,int len)
{
	Bignum y;
	y.len=x.len+len;
	for(int i=1;i<=x.len;i++)
	y.a[i+len]=x.a[i];
	return y;
}
Bignum operator/(Bignum x,Bignum y)
{
	Bignum z;
	z.len=x.len;
	for(int i=z.len;i;i--)
	{
		for(int k=9;k>0;k--)
		if(shift(y,i-1)*k<=x)
		{
			z.a[i]=k;
			x=x-shift(y,i-1)*k;
			break;
		}
	}
	while(z.len>1&&z.a[z.len]==0)z.len--;
	return z;
}

(等老师的代码)

高精度求最大公约数

组合数

n=n1n2n3n4....nk
m=m1
m2m3m4....mk
\(C_n^m\)=\(C_{m1}^{n1}\)*\(C_{m2}^{n2}*\)...\(C_{mk}^{nk}\)

筛法

1、线性筛
因为许多数会被重复筛掉,如6既被2筛也被3筛。
做法:建立一个素数集合,保证每个数只被最小质因子筛掉

矩阵乘法

拓展欧几里得

任意d,gcd(a,b) = d;
都存在x,y,使ax+by = d

posted @ 2020-01-17 23:04  qmings  阅读(171)  评论(0)    收藏  举报