(不是数学课)
标签(空格分隔): 课堂笔记
最大公约数(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=m1m2m3m4....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