积性函数筛 线性筛

积性函数

积性函数:互素的两个数,f(ab)=f(a)f(b)

完全积性函数:任意的两个数,f(ab)=f(a)f(b)

性质

如果f是完全积性函数

f(n)=f(p1)^e1 * f(p2)^e2 * ... * f(pr)^er

欧拉函数、莫比乌斯函数、因子个数函数都是积性函数,但不一定完全积性

线性筛 

作用:

1、在O(n)的时间内求出n以内的所有素数

2、用于在线性时间内求出积性函数值

保证了每一个n都被他最小的质因数筛掉

利用线性筛求积性函数时,需要处理三种情况

1、f(p),p是素数

2、f(p*i), 其中p不是i的约数,根据积性函数性质直接等于f(p)f(i)

3、f(p*i),其中p是i的约数,需要利用函数各自的性质,不如说是寻找到 f(p^k)与f(p^(k-1))的递推关系,可以这么思考的原因是因为i里面已经蕴含了f(p^(k-1))(积性函数),这样我们只要找到递推关系式就可以直接搞出来

积性函数的关键是如何求 f(p^k)

1、观察线性筛法中的步骤,筛掉的同时还得到了它最小的质因数p,我们希望能够知道p在n中的次数,这样就能利用

     f(n)=f(p^k) * f(n/(p^k))求出f(n)

2、令n=p*m,由于p是n最小的质因数,若p^2|n,则p|m,并且p也是m最小的质因数。

     这样在进行筛法的同时,记录每个合数最小质因数的次数(有的时候要记有的时候不要记),就能算出新筛去合数最小质因数的次数

那么我们来举个例子

phi[p^k]=p*phi[p^(k-1)]=(p-1)*p^(k-1),证明暂时略

mu[p^k]=0,当k>=2的时候

所以下面给出代码

#include<cstdio>
#include<iostream>
#include<cstring>
#define ll long long 
using namespace std;
 
const int MAXN=1000005;
bool vis[MAXN];
ll mu[MAXN];
int i,n,T;
ll prime[MAXN];
ll phi[MAXN]; 
int Cs[MAXN];   // 用于保存每个 
ll f[MAXN];
ll la,lb,ra,rb,k,p,ans,d,extra;
 
 
 
void Get_mu(int n)  
{  
    int cnt=0;  
    memset(vis,0,sizeof(vis));  
    memset(mu,0,sizeof(mu));
    mu[1]=1;	// 积性函数f(1)肯定都是一 
    for(int i=2;i<n;i++) {  
        if(!vis[i]) {  
            prime[cnt++]=i;  
            mu[i]=-1;
        }  
        for(int j=0;j<cnt&&i*prime[j]<n;j++) {  
            ll k=i*prime[j];  
            vis[k]=1;  
            if(i%prime[j]==0) {  
            	mu[k]= 0;
                break;  
            }  
            else mu[k]=-mu[i];  
        }  
    }  
}
  

void Get_phi(int n)  
{  
    int cnt=0;  
    memset(vis,0,sizeof(vis));  
    memset(prime,0,sizeof(prime));
    memset(phi,0,sizeof(phi));
    phi[1]=1;
    for(int i=2;i<n;i++) {  
        if(!vis[i]) {  
            prime[cnt++]=i;  
            phi[i]=i-1;
        }  
        for(int j=0;j<cnt&&i*prime[j]<n;j++) {  
            ll k=i*prime[j];  
            vis[k]=1;  
            if(i%prime[j]==0) {  
            	phi[k]=phi[i]*prime[j];
                break;  
            }  
            else phi[k]=phi[i]*(prime[j]-1);  
        }  
    }  
}   

int main() {
	Get_mu(MAXN-5);
	Get_phi(MAXN-5);
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值