莫比乌斯函数与欧拉函数

积性函数

两个互质的整数m,n;
若满足f(nm)=f(n)∗f(m)f(nm)=f(n)*f(m)f(nm)=f(n)f(m)
这就是一积性函数

两个任意的整数m,n;
若满足f(nm)=f(n)∗f(m)f(nm)=f(n)*f(m)f(nm)=f(n)f(m)
这就是一完全积性函数

欧拉函数


欧拉函数:在n范围内与n互质的个数
ϕ(n)=∑i=1n[gcd(i,n)=1]\phi(n)=\sum_{i=1}^n[gcd(i,n)=1]ϕ(n)=i=1n[gcd(i,n)=1]
n=p11∗p22...∗pmmn=p_1^1*p_2^2...*p_m^mn=p11p22...pmm

所以:ϕ(n)=∑i=1n[gcd(i,n)=1]=n∗(1−1/pi)∗(1−1/p2)...∗(1−1/pm)\phi(n)=\sum_{i=1}^n[gcd(i,n)=1]=n*(1-1/p_i)*(1-1/p_2)...*(1-1/p_m)ϕ(n)=i=1n[gcd(i,n)=1]=n(11/pi)(11/p2)...(11/pm)

ϕ(1)=1\phi(1)=1ϕ(1)=1
代码如下:
模板

莫比乌斯函数与欧拉函数

莫比乌斯函数

莫比乌斯函数定义

这,是莫比乌斯函数的定义,这时候有人就要问了:

“兄弟兄弟,这式子太麻烦了,我看不懂啊,能不能换个更加通俗易懂的方法?”
“有的兄弟,有的,像这样的通俗解法还有好几个”

莫比乌斯函数完整定义的通俗表达:
1)μ(1)=1;
2)当n存在平方因子时,μ(n)=0;
3)当n是素数或奇数个不同素数之积时,μ(n)=-1;
4)当n是偶数个不同素数之积时,μ(n)=1。

如何求解莫比乌斯函数 我们根据定义,直接进行质因数分解。碰到平方因子直接返回 0 ,
否则每次碰到质因数乘一个 -1 即可。总体时间复杂度是 O(√n)

但是平常做题经常会用到很多个数的莫比乌斯函数值,那么我们就不能用这种方法求了。我
们知道莫比乌斯函数是积性函数,所以很方便使用线性筛求解莫比乌斯函数

μ(1)=1\mu(1)=1μ(1)=1
找到一个质数x,则μ(x)=−1找到一个质数x,则\mu(x)=-1找到一个质数x,μ(x)=1
对于一个和数x,如果有平方因子,μ(x)=0,否则利用积性函数性质计算对于一个和数x,如果有平方因子,\mu(x)=0,否则利用积性函数性质计算对于一个和数x,如果有平方因子,μ(x)=0,否则利用积性函数性质计算

我们再来把欧拉函数加入进去

1.若 n 是素数, φ(n)=n−1φ(n)=n-1φ(n)=n1,这个由定义可知。
2.若 n = pk ,φ(n)=pk−pk−1φ( n ) = pk - pk-1φ(n)=pkpk1 ,这个在之前已经得出。
3.若 n 是奇数, φ(2n)=φ(n)φ( 2n ) = φ( n )φ(2n)=φ(n),因为 n 和 2 互质,φ(2)=1φ(2)=1φ(2)=1,由积性函数的性质可得
4. ∑d∣nϕ(d)=n\sum_{d|n}\phi(d)=ndnϕ(d)=n
5. 若 p∣np | npnp2∣np2 | np2∣n ,则\ ϕ(n)=ϕ(n/p)=p\phi(n)=\phi(n/p)=pϕ(n)=ϕ(n/p)=p
这时我们就能用以上性质用线性筛筛欧拉函数了

模板代码:

整合后代码:

int cnt=0,prime[N],miu[N],phi[N];
bool vis[N]; 
void ola(int n){
	vis[1]=miu[1]=phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			miu[i]=-1;
			phi[i]=i-1;
		}
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				
				miu[i*prime[j]]=0;
				phi[i*prime[j]]=phi[i]*prime[j];
				
				break;
			}
			miu[i*prime[j]]=-miu[i];
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
		}
	}
}

例题:

Farey数列

AC代码


注意数据量,别忘开long long!!!


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int cnt=0,prime[N],phi[N];
bool vis[N]; 
void ola(int n){
	vis[1]=phi[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			phi[i]=i-1;
		}
		
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				
				phi[i*prime[j]]=phi[i]*prime[j];
				
				break;
			}
			phi[i*prime[j]]=phi[i]*phi[prime[j]];
			//phi[i*prime[j]]=phi[i]*(prime[j]-1);
		}
	}
}
int f[N];
signed main(){
    ola(N);
    
    f[1]=0;
    for(int i=2;i<=N;i++){
        f[i]=f[i-1]+phi[i];
    }
    
    int n;
	while(cin>>n&&n!=0){
	    cout<<f[n]<<"\n";
	}
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值