关于素数

    xiaoxiao2021-12-14  19

    基本了解:

    1.算术基本定理:每个大于1的自然数均可写为质数的积,而且这些素因子按大小排列之后,写法仅有一种方式。例如:6936=2^3*3*17^2,1200=2^4*3*5^2。

    2.由于任何一个合数n至多会有一个大于根号n的因子.——这点很重要

    3.最小的质数为2.

    一、质因数分解:

    cnt=0; //cnt为素因子个数,p数组存的是素因子,num存的是每个素因子的指数。 for(int i=2;i*i<=n;i++) { if(n%i==0) { ++cnt; p[cnt]=i; num[cnt]=0; while(n%i==0) { ++num[cnt]; n/=i; } } } if(n>1)//最多有一个大于sqrt(n)的素因子 { ++cnt; p[cnt]=n; num[cnt]=1; }

    二、素数测试:判定一个数字n是不是质数:拿1 ~n 的所有数字来试除

    bool divisibiity_test(int n) {     for (int i=2; i<n; i++)         if (n % i == 0)             return false;   // 不是质数     return true;    // 是质数 } 改进:一个数至少有一个比sprt(n)小的质因数。 bool divisibiity_test(int n) {       for (int i=2; i<=sqrt(n); i++)         if (n % i == 0)             return false;     return true; } 时间复杂度:O(sqrtN) 

    三、Eratosthenes筛法

    算法描述:

    1.列出所有正整数。

    2.从2开始,删掉 2 的倍数。找下一个未被删掉的数字。

    3.找到 3 ,删掉 3 的倍数。找下一个未被删掉的数字

    4.找到 5 ,删掉 5 的倍数。

    重复步骤,就能删掉所有合数,找到所有质数。

    bool prime[20000000]; void eratosthenes() {     memset(prime,1,sizeof(prime));     prime[0] = 0;  prime[1] = 0; // 0 和 1 不是质数     for (int i=2; i<20000000; i++)         if (prime[i]==1) // 删掉质数i的倍数             for (int j=i+i; j<20000000; j+=i)                 prime[j] = 0; } 改进:删掉质数 i 的倍数时,早已删掉1 倍~ i-1 倍之间的合数了,所以直接从i倍开始删除。

    当删去2的倍数时就已经删去6了,所以从3开始只要从9开始删就行。

    void eratosthenes(){     memset(prime,1,sizeof(prime));     prime[0] = 0;prime[1] = 0;     for (int i=2; i<20000000; i++)         if (prime[i]==1)       //删掉i的倍数从i倍开始。             for (int j=i*i; j<20000000; j+=i)                 prime[j] = 0; } 四、欧拉函数

    1.定理:对正整数n,欧拉函数φ(phi)指是小于n的所有数中与之互质的个数(包含1)。如φ(8)=4,因为1,3,5,7均和8互质。

    2.表达形式:

    3.计算公式:

    4.性质:

    a)当p为质数时, φ(p) = p – 1。

    b)对于互质的正整数a和n,有a^φ(n) ≡ 1 (mod n) 

    c)费马小定理:若正整数a 与素数p 互质,则有a^(p - 1)≡1 mod p。

    d)当n为奇数时φ(2n)=φ(n).

    e)当n和m互质时,φ(n*m)=φ(n)*φ(m).

    f)若n=p^k(p为质数),φ(n)=p^k-p^(k-1).

    朴素算法实现:

    1.根据公式1:n=p1^k1*p2^k2*…*pr^kr和公式2:φ(n)=n* (1-1/p1) *…* (1-1/pr)。

    2.可将公式2可拆成n* (1-1/p1)=n-n/p1计算。

    int euler(int n) { int i,ans=n; for(i=2; i*i<=n; i++) if(n%i==0) { ans=ans-ans/i; do n/=i;//把该素因子全部约掉 while(n%i==0); } if(n>1) ans=ans-ans/n; return ans; } 快速欧拉:

    void fasteuler() { memset(phi,0,sizeof(phi)); for (int i=2;i<=1000000;i++)//筛选求phi { if (!phi[i])//当phi[i]未访问,就是phi[i]=0的时候. { for (int j=i;j<=1000000;j+=i) { if (!phi[j])//当phi[j]未访问 phi[j]=j;//将phi[j]设为访问且值为j,方便接下来计算。 phi[j]=phi[j]-phi[j]/i;//算出phi[j]的个数(欧拉公式)。 }}}}

    转载请注明原文地址: https://ju.6miu.com/read-970575.html

    最新回复(0)