质数
积性函数
若函数 \(f(1)=1\),并且对于 \(gcd(x,y)=1,f(xy)=f(x)*f(y)\),则 \(f(i)\) 为积性函数。
若函数 \(f(1)=1\),并且 \(f(xy)=f(x)*f(y)\),则 \(f(i)\) 为完全积性函数。
除数函数,欧拉函数为积性函数。
判断单个素数
inline bool isprime(int x){
if(x<2)return false;/*2以内不是质数*/
int sq=sqrt(x)+1;
for(int i=2;i<=sq;i++)if(x%i==0)return false;/*因子最多根号个,扫描每个因子*/
return true;
}
埃氏筛
任意整数的倍数都不是倍数,标记这些倍数,没有被标记的就是质数,时间复杂度 \(O(N* \log\log N)\).
inline void sieve(int n){
for(int i=2;i<=n;i++){
if(!v[i])prime[++m]=i;/*没有被标记的是质数*/
for(int j=i*i;j<=n;j+=i)v[j]=1;/*标记当前数每个倍数*/
}
}
线性筛,即欧拉筛
控制每个数只被标记一次,即被它的最小质因子标记。
inline void sieve(int n){
for(int i=2;i<=n;i++){
if(!v[i])prime[++m]=i,miv[i]=i;/*i的最小质因子是i*/
for(int j=1;j<=m&&i*prime[j]<=n;j++){
v[i*prime[j]]=1;
miv[i*prime[j]]=prime[j];/*i*prime[j]的最小质因子是prime[j]*/
if(miv[i]==prime[j])break;/*当i中也含有质因子prime[j]时停止*/
}
}
}
筛法求约数个数
设 \(d_i\) 表示 \(i\) 的约数个数,\(num_i\) 表示 \(i\) 的最小质因子出现的次数。
对于 \(n=\prod_{i=1}^{m}{p_i^{c_i}}\) ,约数个数为 \(\prod_{i=1}^{m}{(c_i+1)}\).
inline void sieve(int n){
d[1]=1;/*1的约数个数是1*/
for(int i=2;i<=n;i++){
if(!v[i])prime[++m]=i,d[i]=2,num[i]=1;/*质数的约数只有1和自己,最小质因子为自己,出现次数为1*/
for(int j=1;j<=m&&i*prime[j]<=n;j++){
v[i*prime[j]]=1;
if(i%prime[j]){/*新出现的最小质因子*/
num[i*prime[j]]=1;/*次数为1*/
d[i*prime[j]]=d[i]*d[prime[j]];/*d[prime[j]]=num[prime[j]]+1=2,约数个数相乘*/
}
else{/*已经出现过的*/
num[i*prime[j]]=num[i]+1;/*累加最小质因子出现次数*/
d[i*prime[j]]=d[i]/num[i*prime[j]]*(num[i*prime[j]]+1);/*先除掉最小质因子的次数清空其影响,再重新计算*/
break;
}
}
}
}
筛法求约数和
设 \(f_i\) 表示 \(i\) 的约数和,\(g_i\) 表示 \(i\) 的最小质因子 \(p\) 的 \(p^0+p^1+...p^c\).
inline void sieve(int n){
f[1]=g[1]=1;
for(int i=2;i<=n;i++){
if(!v[i])prime[++m]=i,f[i]=g[i]=i+1;
for(int j=1;j<=m&&i*prime[j]<=n;j++){
v[i*prime[j]]=1;
if(i%prime[j]){
g[i*prime[j]]=prime[j]+1;
f[i*prime[j]]=f[i]*f[prime[j]];
}
else{
g[i*prime[j]]=g[i]*prime[j]+1;
f[i*prime[j]]=f[i]/g[i]*g[i*prime[j]];
break;
}
}
}
}

浙公网安备 33010602011771号