线性筛法求解欧拉函数以及欧拉反演

欧拉函数

定义:

1~n中与n互质的数的个数称为欧拉函数,记为 φ ( n ) \varphi(n) φ(n)
φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1
φ ( 2 ) = 1 \varphi(2)=1 φ(2)=1
φ ( 3 ) = 2 \varphi(3)=2 φ(3)=2

性质:

1、若p是质数, φ ( p ) \varphi(p) φ(p)=p-1

2、若p是质数, φ ( p k ) \varphi(p^{k}) φ(pk)= p k − 1 ∗ ( p − 1 ) p^{k-1}*(p-1) pk−1∗(p−1)

性质二解释:
1 , . . . , p , . . . , 2 ∗ p , . . . . . . , p k 1,...,p,...,2*p,......,p^{k} 1,...,p,...,2∗p,......,pk

可以将它们分段处理:

1,...,pp+1,...,2\*p,...

可以发现每一段的大小都是p,所以会有 p k / p p^{k}/p pk/p段,每一段都有(p-1)个,所以答案就是上述的描述

3、积性函数:若gcd(m,n)=1,则 φ ( m n ) = φ ( m ) ∗ φ ( n ) \varphi(mn)=\varphi(m)*\varphi(n) φ(mn)=φ(m)∗φ(n)

计算公式:

总结:

根据推导的公式可以得出欧拉函数只与n和其1~n之间的质数有关

代码:

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
using namespace std;
const int N=2e5+10;
int primes[N],cnt=0;
bool vis[N];
int phi[N];
void init(){
	phi[1]=1;
	for(int i=2;i<N;i++){
		if(!vis[i])primes[++cnt]=i,phi[i]=i-1;
		for(int j=1;i*primes[j]<N;j++){
			vis[i*primes[j]]=true;
			if(i%primes[j]==0){
				phi[i*primes[j]]=primes[j]*phi[i];
				break;
			}
			else{
				phi[i*primes[j]]=(primes[j]-1)*phi[i];
			}
		}
	}
}
void solve(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)cout<<phi[i]<<' ';
	cout<<'\n';
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	init();
	int _=1;
	//cin>>_;
	while(_--)solve();
}

欧拉反演

定义:

对于任意的正整数n有:
∑ d ∣ n ϕ ( d ) = n \sum_{d \mid n}\phi(d)=n ∑d∣nϕ(d)=n

n的所有的因数(包含1和n本身)的欧拉函数之和等于n

证明:

应用:

求解 ∑ i = 1 n g c d ( i , n ) \sum_{i=1}^{n}gcd(i,n) ∑i=1ngcd(i,n)的时候可以优化,步骤如下:
g c d ( i , n ) = ∑ d ∣ g c d ( i , n ) ϕ ( d ) gcd(i,n)=\sum_{d|gcd(i,n)}\phi(d) gcd(i,n)=∑d∣gcd(i,n)ϕ(d)

例题:

https://codeforces.com/contest/1900/problem/D

题目思路:

代码:

cpp 复制代码
#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
using namespace std;
const int N=2e5+10;
int primes[N],cnt=0;
bool vis[N];
int phi[N];
void init(){
	phi[1]=1;
	for(int i=2;i<N;i++){
		if(!vis[i])primes[++cnt]=i,phi[i]=i-1;
		for(int j=1;i*primes[j]<N;j++){
			vis[i*primes[j]]=true;
			if(i%primes[j]==0){
				phi[i*primes[j]]=phi[i]*primes[j];
				break;
			}
			else{
				phi[i*primes[j]]=phi[i]*(primes[j]-1);
			}
		}
	}
}
void solve(){
	int n;
	cin>>n;
	vector<int>a(n+1);
	for(int i=1;i<=n;i++)cin>>a[i];
	sort(a.begin()+1,a.end());
	vector<int>cnt(N);
    int sum=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j*j<=a[i];j++){
			if(a[i]%j==0){
				sum+=(n-i)*phi[j]*cnt[j];
				cnt[j]++;
				if(j*j!=a[i]){
					sum+=(n-i)*phi[a[i]/j]*cnt[a[i]/j];
					cnt[a[i]/j]++;
				}
			}
		}
	}
	cout<<sum<<'\n';
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	init();
	int _=1;
	cin>>_;
	while(_--)solve();
}
相关推荐
倒头就睡的小比特18 小时前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!18 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼19 小时前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光20 小时前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark20 小时前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her121 小时前
并查集-听课笔记
笔记·算法·并查集
码流子21 小时前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven21 小时前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark21 小时前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218611 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法