Loading

素数筛以及欧拉函数

1.素数筛

埃式筛法

我们用一个很简单的思想质数的倍数就是质数

我们举一个例子\(2,3,4,5,6,7,8,9,10,11,12,13,14,15,16\)

\(2\)为基本数,我们筛一遍就只剩下\(2,3,5,7,9,11,13,15\)

再用\(3\)筛......

欧拉筛

就是在埃式筛的基础上改进,请看代码

void init(int n)
{
    for(int i = 2; i <= n; i++)
    {
        if(vis[i] == 0)
            primes.push_back(i);
        for(int j = 0; j < primes.size(); j++)
        {
            int p = primes[j];
            if(p * i > n)
                break;
            vis[p * i] = 1;
            if(i % p == 0)//关键!!!筛到这里我们吧剩下的留给以后筛!!
                break;
        }
    }
    return ;
}

2.欧拉函数

定义一个函数\(\varphi(x)\)表示不超过\(x\)且与\(x\)互质的正整数的个数,\(1\)也算在里面,不算自己。

比如说\(\varphi(10)=4(1,3,7,9),\varphi(12)=4(1,5,7,11)\)

性质一

如果\(p\)是质数,那么\(\varphi(p^n)=p^{n-1}(p-1)\)

证明:在\(p^n\)内显然有整除关系的是\(p^1,p^2,p^3...,p^{n-1}\)

我们在对于每一个数在搭上一个系数,这样就得出了\(\varphi(p)=p^n-p^{n-1}\)

这一条性质在我们求欧拉函数是有用。

性质二

如果\(a\)\(x\)的约数,那么\(\varphi(ax)=a\times\varphi(x)\)

证明:

我们假设\(\varphi(x)\)包括\(m_1,m_2,m_3,...,m_{\varphi(x)}\)

我们分\(a\)组,第\(i\)组是\(m_1\times ix,m_2\times ix,...,m_{\varphi(x)}\times ix\)

显然,这一些组里的数都与\(ax\)互质(凑不够)

如果\(a\)不是\(x\)的因数,那么\(\varphi(x)\)可能会有更多(证明可能不太严谨

严格的证明请自行百度

性质三

如果\(a,b\)互质,那么\(\varphi(a)\times\varphi(b)=\varphi(a\times b)\)

证明:不会

实现

对欧拉筛进行魔改

bool vis[maxn]; 
void init(int n)
{
    phi[1] = 1;
    for(int i = 2; i <= n; i++)
    {
        if(vis[i] == 0)
            primes.push_back(i), phi[i] = i - 1; // 性质一,指数为1的情形
        for(int j = 0; j < primes.size(); j++)
        {
        	int p = primes[j];
            if (p * i > n)
                break;
            vis[p * i] = 1;
            if(i % p == 0)
            {
                phi[p * i] = phi[i] * p; // 性质二
                break;
            }
            else
                phi[p * i] = phi[p] * phi[i]; // 这时肯定互质,用性质三
        }
    }
    return ;
}
posted @ 2021-02-25 20:17  zhangwenxuan  阅读(125)  评论(0)    收藏  举报