• 数论学习(2019.4.4


    今天钟长者讲课吖qqqq

    一、质数

    有一个定理: 设p为质数,若p | ab ,则 p | a或者p | b;

    二、整数唯一分解定理

    这个证明是用的反证法:

    1.存在性

    设立N为不满足条件的最小的数

    若N为质数 显然不成立

    若N为合数 由于N = an 则n也不能分解 因此不成立

    2.唯一性

    设N为不可以被整除的最小的数

    若N为质数 因为N = N^1 显然不成立

    若N为合数 N = P * N / P 因为N为最小的,而 N / P却更小,因此不成立

    证毕

    三、Miller_Rabin素性测试

    如果N为素数,取a < n;

    设n - 1 = d * 2 ^ r

    则下列两个结论中必定满足一个:

    1.

    2.

    先贴代码吧:

    其中定义的gg[]数组就是8个素数

    证明:

    我们使用平方差公式,运用欧拉定理进行证明:

    (手写qwq)

     

    (像素好低啊q)

    三、筛法

    埃氏筛,欧拉筛昨天讲了,代码也放在昨天了,今天就不再提起了

    四、最大公因数

    欧几里得算法的核心思想:

    gcd(a,b) = gcd(b,a - b)

    推导得出: gcd(a,b) = gcd(a,a % b)

    证明:

    反证法:

    五、裴蜀定理

     

    还有,解释了一下充要条件qqq

    证明过程:

     

    这里可以用裴蜀定理证明这个定理: 设p为质数,若p | ab ,则 p | a或者p | b;

     六、拓展欧几里得

    求 ax + by = gcd(a,b)的一组解(x,y)

    推导式:

    将 a % b 改写为 a - a / b * b 

     Code:

    七、中国剩余定理:

     正经做法:

    证明过程:

     这个题做法即为两两合并

    对于k个方程

    则进行k - 1次合并

    举个栗子:

     邪门做法(大数翻倍法):

     我们一直对于两个方程式中

    不断地将x += p1

    直到满足第二个式子

    然后对于这个进行排序,选取较大的数

    则可得其时间复杂度为: O(p1 + p2 + ... +pn - max(p1,p2,...,pn));

    被卡的情况:两个10 ^ 9的p的时候

    八、BSGS算法  (Baby Step Giant Step)

    qwq(北上广深)(拔山盖世)算法

    这个问题主要是求给定a,b,p,求最小的非负整数x,满足  ax ≡ b(mod p)

    方法:

    r * a ^ sqrt(m) = b;

    左右同乘逆元

    则变为: r = b * -sqrt(m);

    我们可以采用分块:

    将其分为 sqrt(m) * sqrt(m)的形式

    还有一个排序的步骤,便于二分

    然后询问在第一行中有没有数可以使得r = b * a ^ -sqrt(m)

    Code:

    #define ll long long
    int size;
    bool erfen(int x)
    {
        int l = 0;
        int r = size;
        while(l + 1 != r)
        {
            int m = (l + r) >> 1;
            if(z[m] >= x)
            r = m;
            else
            l = m;
        }
        return z[r] == x;
    }
    int kuaisumi(int base,int b,int p)
    {
        int ans;
        while(b)
        {
            if(b & 1)
            ans *= base;
            base *= base;
            b >>= 1;
        }
        return ans;
    }
    int bsgs(int a,int b,int p)
    {
        size = sqrt(p);
        int nowv = 1;
        for(int i=1;i<=size;i++)
        {
            nowv = (ll)nowv * a % p;
            z[i] = nowv;
            if(z[i] == b)
            return i;
        }
        sort(z + 1,z + size + 1);
        for(int i=2;(i-1)*size+1<=p;i++)
        {
            int y =(ll)b * kuaisumi(kuaisumi(a,size * (i - 1),p),p - 2,p);
            if(erfen(y))
            {
                for(int j=(i-1)*size+1;j<=i*size;j++)
                if(kuaisumi(a,j,p) == b)
                return j;
            }
        }
        return -1;
    }

    九、线性求逆元

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define ll long long
    using namespace std;
    ll n,p,m,k,r,x;
    ll inv[20000528];
    int main()
    {
        scanf("%lld%lld",&n,&p);
        inv[1]=1;
        if(n<=1)
        printf("1
    ");
        for(int i=2;i<=n;i++)
        {
            inv[i]=p-(p/i)*inv[p%i]%p;
            printf("%lld
    ",inv[i]);
        }
        return 0;
    }

    九、积性函数

    定义:

    若gcd(x,y) = 1,有f(xy) = f(x) * f(y)

    常见的积性函数:

    欧拉函数为积性函数的证明(因子数目与因子之和的大同小异)

    莫比乌斯函数:

    mu[i] 

    对于 i 将其分解(唯一分解定理) 为 p1 ^ r1 ...... pn ^ rn

    设 r = max(r1,r2,...,rn);

    设 k = r1 + r2 +...+ rn;

    则:

    mu[i] = 1                       i == 1 的时候
    mu[i] = 0                       r > 1 的时候
    mu[i] = (-1) ^ k             r == 1 的时候

    Code:

    这其中;

    phi[] 欧拉函数

    mu[] 莫比乌斯函数

    线性筛求积性函数

    莫比乌斯是积性函数的证明:(这个要用到组合数,长者说明天再讲的)

    留个坑,有时间再补吧

    十、莫比乌斯反演 

    F(n)和f(n)是定义在非负整数集合上的两个函数:

    证明:

    十一、数论函数的卷积

     

    qqq

    还有一些老师发的Code:

    Miller_Rabin

    int gg[8] = {2,3,5,7,13,29,37,89};
    
    bool miller_rabin(int a,int n)
    {
        int d=n-1,r=0;
        while (d%2==0)
            d/=2,r++;
        int x = kuaisumi(a,d,n);
        if (x==1) return true;
        for (int i=0;i<r;i++)
        {
            if (x==n-1) return true;
            x=(long long)x*x%n;
        }
        return false;
    }
    
    bool is_prime(int n)
    {
        if (n<=1) return false;
        for (int a=0;a<8;a++)
            if (n==gg[a]) return true;
        for (int a=0;a<8;a++)
            if (!miller_rabin(gg[a],n)) return false;
        return true;
    }

    线性筛积性函数中的欧拉函数和莫比乌斯函数

    memset(not_prime,0,sizeof(not_prime));
    
    for (int i=2;i<=n;i++)
    {
        if (!not_prime[i]) 
        {
            prime[++ prime_cnt] = i;
            phi[i] = i-1;
            mu[i] = -1;
        }
        for (int j=1;j<=prime_cnt;j++)
        {
            int x = i * prime[j];
            if (x>n) break;
            
            not_prime[x] = true;
            phi[x] = phi[i] * phi[prime[j]];
            mu[x] = mu[i] * mu[prime[j]];
            
            if (i % prime[j] == 0) 
            {
                phi[x] = phi[i] * prime[j];
                mu[x] = 0;
                break;
            }
        }
    }
  • 相关阅读:
    Selenium IDE
    selenium简介
    Java程序要操作数据库,一定要使用JDBC技术吗?
    JDBC几个接口分区叫什么?它们分别有什么用?
    JDBC的全称是什么?
    什么时候使用session?什么时候使用application?
    内置对象session和application的作用是什么?
    修改表单中为什么要使用隐藏域?
    如何创建一个不能修改的属性?
    如何修改属性?
  • 原文地址:https://www.cnblogs.com/lyp-Bird/p/10659927.html
Copyright © 2020-2023  润新知