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

猜你喜欢

转载自www.cnblogs.com/qmings/p/12207847.html