看来别人的博客,对筛法有了新的认识
1.Eratosthenes筛法(Sieve of Eratosthenes)
这是一种简单检定素数的算法。据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274~194年)发明的,又称埃拉托斯特尼筛法(sieve of Eratosthenes)。
也就是我们常用的素数筛选法
我们第一次遇见的便是素数,然后拿一个素数可以把和此素数相关的合数筛选出来
bool book[N];
int prime[N];
int res;
void eratosthenes_sieve()
{
res=0;
memset(book,false,sizeof(book));
for(int i=2;i<N;i++)
{
if(!book[i])
{
prime[res++]=i;
for(int j=28i;j<N;j+=i)
book[j]=true;
}
}
}
2.Euler筛法(Sieve of Euler)
bool book[N];
int prime[N];
int res;
void eratosthenes_sieve()
{
res=0;
memset(book,false,sizeof(book));
for(int i=2;i<N;i++)
{
if(!book[i]) prime[res++]=i;
for(int j=0;i*prime[j]<N&&j<res;j++)
{
book[i*prime[j]]=true;
if(i%prime[j]==0)break;
}
}
}
很多相关的积性函数都可以用欧拉线性筛法得到
φ(n) - 欧拉函数
μ(n) - 莫比乌斯函数,关于非平方数的质因子数目
gcd(n,k) - 最大公因子,当k固定的情况
d(n) - n的正因子数目
σ(n) - n的所有正因子之和
σk(n) - 因子函数,n的所有正因子的k次幂之和,当中k可为任何复数。
1(n) - 不变的函数,定义为 1(n) = 1 (完全积性)
Id(n) - 单位函数,定义为 Id(n) = n(完全积性)
Idk(n) - 幂函数,对于任何复数、实数k,定义为Idk(n) = n^k (完全积性)
ε(n) - 定义为:若n = 1,ε(n)=1;若 n > 1,ε(n)=0。别称为“对于狄利克雷卷积的乘法单位”(完全积性)
λ(n) - 刘维尔函数,关于能整除n的质因子的数目
γ(n), 定义为γ(n)=(-1)^ω(n),在此加性函数ω(n)是不同能整除n的质数的数目
另外, 所有狄利克雷特征均是完全积性的[1]
欧拉函数
const int N=1100;
const int maxn=1009;
int prime[N],euler[N],ans[N];
int res;
void eratosthenes_sieve()
{
res=0;
memset(euler,0,sizeof(euler));
ans[1]=3;
for(int i=2;i<maxn;i++)
{
if(euler[i]==0)
prime[res++]=i,euler[i]=i-1;
for(int j=0;j<res&&i*prime[j]<maxn;j++)
{
if(i%prime[j]==0)
{
euler[i*prime[j]]=euler[i]*prime[j];
break;
}
euler[i*prime[j]]=euler[i]*(prime[j]-1);
}
ans[i]=ans[i-1]+(2*euler[i]) ;
}
}
emmmmm.......就目前来看好像积性函数都能用线性筛,我也不知道是不是,希望有大佬能留言区告知一下
分清一下 i%prime[j]==0 与 i%prime[j]!=0的情况讨论
而这里就是思考的所在
n的正因子数目
bool book[N];
int prime[N],d[maxn],temp[maxn];
int res;
void eratosthenes_sieve()
{
res=0;
memset(book,false,sizeof(book));
for(int i=2;i<maxn;i++)
{
if(!temp[i])
prime[res++]=i,d[i]=2;
for(int j=0;j<res&&i*prime[j]<maxn;j++)
{
if(i%prime[j]==0)
{
temp[i*prime[j]]=prime[j]*temp[i];
d[i*prime[j]]=d[i/temp[i]]*(d[temp[i]]+1);
break;
}
temp[i*prime[j]]=prime[j];
d[i*prime[j]]=2*d[i];
}
}
求 s u m ( d ) = ∑p|d μ ( dp )
const int maxn = 10000010;
int prime[maxn],mu[maxn],sum[maxn];
bool check[maxn];
void Mobius(){
memset(check,false,sizeof(check));
mu[1] = 1;
prime[0] = 0;
for(int i=2;i<maxn;i++){
if(!check[i]){
mu[i] = -1;
sum[i] = 1;
prime[++prime[0]] = i;
}
for(int j=1;j<=prime[0];j++){
if(i*prime[j] >= maxn) break;
check[i*prime[j]] = true;
if(i % prime[j]){
mu[i*prime[j]] = -mu[i];
sum[i*prime[j]] = mu[i] - sum[i];
}
else{
mu[i*prime[j]] = 0;
sum[i*prime[j]] = mu[i];
break;
}
}
}
}