素数筛以及欧拉函数
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 ;
}

浙公网安备 33010602011771号