• 数论基础


    数学

    //本篇为学习记录,会一直更新

    常见符号:

    1. 整除符号:(x) (|) (y),​ (x)整除(y)

    2. 取模符号:(x) (mod) (y)(x)除以(y) 的余数

    3. 互质符号: (x) (ot) (y)(x)除以(y) 的余数

    4. 最大公约数:(gcd(x,y)),简写为((x,y))

    5. 最小公倍数:(lcm(x,y)),简写为(left[x,y ight])

    6. 求和符号:(sum)

    7. 求积符号:(prod)

    数论基础:

    1)素数判定:

    如果存在一个整数(k),使得(a=kd),则称(d)整除(a),记作(d) (|) (a),即(a)(d)的倍数,(k)叫做他们的约数

    那么如果除了(1)和它本身外,不存在任意的(k),使得(d) (|) (a),那么就叫这个(a)为素数(质数)

    (1)既不是质数也不是合数

    素数的判定方法:

    1. (O(n))

    bool is_prime(int n)
    {
        int flag=0;
        for(int i=2;i<n;i++)
        {
            if(n%i==0) 
            {
                flag=1;
                break;
            }
        }
        if(flag) return 0;
        else return 1;
    }
    

    2.(O(sqrt(n)))

    因为质数的分布是以(sqrt(n))为界限对称分布的,所以只去遍历((2-sqrt(n)))就可以得到所有的约数

    bool is_prime(int n)
    {
        int flag=0;
        for(int i=2;i*i<=n;i++)
        {
            if(n%i==0) 
            {
                flag=1;
                break;
            }
        }
        if(flag) return 0;
        else return 1;
    }
    

    2) 素数筛

    假设(n=1000000),如果我们想要知道(1-n)之间有多少个素数,分别是多少,很明显,直接对每一个数去判断他是否是质数的时间复杂度是(o(n*sqrt(n)))

    对于(1000000)的数据规模预处理也是有可能 tle 的,所以我们并不考虑这样的预处理方式

    对于(iin[1,n])的每一个数(i),如果(i)是一个合数的话,只让他被最小的质因子筛一次,时间复杂度(O(n))

    每次我们遍历([2,n]) 的每一个数,如果遍历到了(i) 那就证明他已经被比他小的数筛过了,如果没有被标记,那就证明他是一个质数,然后我们遍历已经被筛过的质数,把他的倍数全都标记上,如果(i\%prime[j]==0),那(i=prime[j]*x) ,下一次循环的(i*prime[j+1]=prime[j]*x*prime[j+1]) ,但(prime[j])一定比(prime[j+1])小,所以就不用再筛下去了,(i*prime[j+1])一定被筛过了

    int vis[maxn],prime[maxn],cnt=0;
    void init(int n)
    {
        vis[0]=1;
        vis[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(!vis[i]) prime[cnt++]=i;
            for(int j=0;j<cnt&&i*prime[j]<=n;j++)
            {
                vis[i*prime[j]]=1;
                if(i%prime[j]==0) break;
            }
        }
    }
    // 质数的vis=0,prime下标从0开始
    

    3) 同余式

    如果两个数(a,b)在模(n)意义下的答案相等,那么我们就说(a)(b)对模(n)同余,记作(a equiv b)

    4) Wilson定理(威尔逊定理)

    当且仅当(p)为素数时 ((p-1)!equiv-1(mod p))

    5) Fermat小定理(费马小定理)

    如果(p)是一个素数,且((0<a<p)) 那么存在(a^{p-1}equiv1(mod p))

    证明:

    (1*a\%p=a_{1})

    (2*a\%p=a_{2})

    (dots)

    ((p-1)*a\%p=a_{p-1})

    进行累乘

    ((p-1)!*a^{p-1}\%p=(p-1)!)

    同除((p-1)!)(a^{p-1}equiv1(mod p))

    [关于为什么(a_1*a_2* dots *a_{p-1}=(p-1)!)的解释] :

    对于$iin [1,p-1] $ 有(a*i\%pequiv b)

    ((a*i\%p-b+p)\%pequiv 0)

    ((a*i-b) | p)

    如果想找到另一个(i')使得(a*i'\%pequiv b) 那么只有(i'=i+p),但(i+p>p-1) 所以不存在这样的(i')

    所以对于$iin [1,p-1] $ 集合(left {a_1,a_2, dots,a_{p-1} ight })等同于集合(left {1,2,dots,p-1 ight })

    (a_1*a_2* dots *a_{p-1}=(p-1)!)

    5) Euler定理(欧拉定理)

    欧拉定理也是费马小定理的一个推广

    我们定义(varphi (n))(iin [1,n])中有多少(i)使(gcd(n,i)=1)

    如果(gcd(a,p)=1) 那么(a^{varphi(p)} equiv 1(mod p))

    (当(p)是素数时,很明显(varphi(p)=p-1),就可以得到费马小定理了)

    定理的证明和Fermat小定理几乎相同,只是要考虑的式子变成了所有与m互素的数的乘积

    5) Fermat素数测试

    Fermat素数测试属于一种随机算法

    对于费马小定理来说,人们发现他的逆命题并不成立,比如(2^{560}\%561equiv1)(561)并不是个素数,(561=11*51)

    人们把这样的数(n)叫做伪素数,即(2^{(n-1)}-1 | n)

    对他进行推广,把(2)替换为任意的素数(a), 满足(a^{(n-1)}\%n=1)的合数(n)叫做以 (a) 为底的伪素数。

    不满足(a^{(n-1)}\%n=1)(n)一定不是素数,我们一般是随机选取有限个数的底数 a ,对 n 进行素性测试。若全部满足,则认为数字 n 是质数,若有一个不满足,则认为数字 n 不是质数

    这样的判断在一定程度上已经足够准确了

    但,对于所有小于 (n) 的底数 (a),都满足(a^{(n-1)}\%n=1) 的数。(前(10)亿个数中,仅有(600)多个这样的数存在)这样的数叫做Carmichael数

    利用二次探测定理可以对上面的素数判定算法作进一步改进,以避免将Carmichael数当作素数,而用这种方式优化过的素数测试算法叫做Miller_Rabin素数测试算法

  • 相关阅读:
    Java生鲜电商平台-微服务架构利弊分析(生鲜小程序/APP)
    实用---eclipse中的代码提示功能
    实验---数据结构中字符串的匹配问题
    实验---实现两个指数递减多项式的和与积
    实验----Java的二维数组的应用及杨辉三角的编写
    你也想成为白帽子么?推荐一份网络安全书单!
    互联网公司的敏捷开发是怎么回事?这一份软件工程书单送给你!
    曾经我也有一个做游戏的梦想,这几本游戏开发的书籍推荐给为未来的游戏工程师
    如何做好Linux服务器运维,你可能需要这一份运维工程师书单!
    如何做好Linux服务器运维,你可能需要这一份运维工程师书单!
  • 原文地址:https://www.cnblogs.com/YangKun-/p/14344385.html
Copyright © 2020-2023  润新知