【模板】各类线性筛法
线性筛法是极其实用而高效的方法,一般是对于数论上的完全积性函数和积性函数才使用这种方法。
积性函数的定义:
-
对于互质的正整数\(p_1p_2\),我们若有在正整数域上定义的函数,\(f(ab)=f(a)f(b)\),则称\(f(x)\)为积性函数。若\(p_1p_2\)扩展到整数域内,则称为完全积性函数。
我们的线性筛法就是基于这样的数学原理,其中,线性筛素数是基础
线性筛素数
(以下代码默认):
#define RP(t,a,b) for(int t=(a),edd=(b);t<=edd;t++)
思想:
- 当我们更新到\(i\)时,我们判断它是否是一个合数(是否被标记过),否则是个质数,加入素数表中。
- 将\(i×prime(j),\)注意\(i\)不能\(|prime(j)\),若发生整除则break,这保证了线性的复杂度
const int maxn=100005;
bool pr[maxn];
vector < int > prime;
inline void gen_prime(){
RP(t,1,maxn-5)
pr[t]=1;
pr[0]=pr[1]=false;
RP(t,2,maxn-5){
if(pr[t])
prime.push_back(t);
RP(i,0,prime.size()-1){
if(t*prime[i]>maxn)
break;
pr[t*prime[i]]=false;
if(!(t%prime[i]))
break;
}
}
return;
}
线性筛\(\phi\)函数,欧拉函数:
关于欧拉函数:
- 对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)
- 对于质数\(p\),显然有\(\phi(p)=p-1\)
- 对于奇数\(p\),易得\(\phi(p)=\phi(2p)\)
- 和费马小定理定理的联系
-
\(a^{\phi(m)} \equiv1\pmod{m}\)
- 当\(m\)是质数时,
- \(a^{m} \equiv a \pmod{m}\)
-
思想:(对于质数\(p\))
- 对于\(p_1p_2\)互质, \(\phi(p_1\times p_2)=\phi(p_1) \phi(p_2)\)
- 若\(i\mod p= 0\), 那么\(phi(i * p)=p \times \phi(i)\)证明略
- 若\(i \mod p ≠0\), 那么\(\phi(i \times p)=\phi(i)\times(p-1)\)
- 质数和欧拉函数一起筛。
const int maxn=100005;
vector < int > prime;
int phi[maxn];
bool usd[maxn];
inline void gen_phi(void){
int cnt=0;
phi[1]=1;
RP(t,2,maxn-5){
if(!phi[t])
phi[t]=t-1,prime.push_back(t);
RP(i,0,prime.size()-1){
if(prime[i]*t>maxn)
break;
if(!t%prime[i]){
phi[t*prime[i]]=phi[t]*prime[i];
break;
}
else
phi[t*prime[i]]=phi[t]*phi[prime[i]];
}
}
}
线性筛莫比乌斯函数,\(\mu(x)\)
思想:
- 莫比乌斯函数只有\(0,1,-1\)三种值。
- 对于\(x=p_1p_2p_3p_4p_5p_6...p_n\),\(p_i\)为互不相同的质数,\(\mu(x)=(-1)^n\)
- 其他情况都为0
const int maxn=100005;
vector < int > prime;
int mu[maxn];
bool usd[maxn];
inline void gen_mu(void){
mu[1]=1;
RP(t,2,maxn){
if(!usd[t])
prime.push_back(t),mu[t]=-1;
RP(i,0,prime.size()-1){
if(prime[i]*t>maxn)
break;
usd[prime[i]*t]=1;
if(!(t%prime[i]))
break;
else
mu[t*prime[i]]=-mu[t];
}
}
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!