基础回顾--素数筛,欧拉函数

谁说胖子不能爱 提交于 2019-11-28 13:41:38

欧拉筛法:

  直接判断素数耗时,换个角度标记非素数,那么没有被标记的就是素数。

  关键点:

  1. 除2之外的偶数必然不是素数,所以只需要遍历奇数
  2. 寻找0-N范围中的素数时,遍历只需要从 2-->sqrt(N+0.5),因为sqrt(N+0.5)之后的数必然在第二层的循环中标记过。
  3. 二层循环的意思:一层循环找到了素数prime,则要将prime的所有倍数都筛去。注意从prime*prime开始筛,因<prime*prime的数必然能被之后找到的prime的倍数筛去。
const int maxn = 10004;
bool vis[maxn];
int prime[maxn], cnt;

void sort_prime() {
    prime[cnt++] = 2;
    int m = (int) sqrt(maxn + 0.5);
    for(int i=3; i<m; i+=2) {
        if(!vis[i]) {
            prime[cnt++] = i;
            for(int j=i*i; j<maxn; j+=i) {
                vis[j] = true;
            }
        }
    }
    return;
}

 

欧拉函数:

  求解所有<=n且与n互素的数的总数,特别的 phi(1) = 1。 (phi其实是数学符号的谐音~)

  根据性质 phi(n) = n*(1-1/p1)*(1-1p2)...*(1-1/pk),pi是n的所有素因子。性质的公式进行变行--> phi(n) = n ∏ [ (pi-1)/pi ] --> 每一步看phi = n,phi = phi / pi * (pi-1)先除后乘防止溢出-->phi = phi - phi/pi -- > phi -= phi/pi

int phi(int N) {
    int tmp = N, n = N;
    for(int i=0; i<cnt && prime[i]<=n; ++i) {
        if(n%prime[i] == 0) {
            tmp -= tmp/prime[i]; //欧拉函数性质推导出的式子
            while(n%prime[i] == 0) // 去掉prime[i]因子
                n /= prime[i];
        }
    }

    //若n != 1,则必然还剩下一个素数没有用
    if(n != 1) tmp -= tmp/n;
    return tmp;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!