欧拉函数φ

函数作用

计算 1 1 1 ~ n n n中有多少个与 n n n互质的数。

函数公式

φ ( n ) = n × p 1 − 1 p 1 × p 2 − 1 p 2 × … … × p m − 1 p m φ(n)=n\times\frac{p_1-1}{p_1}\times\frac{p_2-1}{p_2}\times……\times\frac{p_m-1}{p_m} φ(n)=n×p1p11×p2p21×……×pmpm1
p i p_i pi N N N分解后的第 i i i个质因数。

公式证明

欧拉函数是积性函数,所以 φ ( a b ) = φ ( a ) ∗ φ ( b ) φ(ab)=φ(a)*φ(b) φ(ab)=φ(a)φ(b)
同理 φ ( n ) = φ ( p 1 c 1 ) × φ ( p 2 c 2 ) × φ ( p 3 c 3 ) × φ ( p 4 c 4 ) × … … × φ ( p n c n ) φ(n)=φ(p_1^{c_1})\timesφ(p_2^{c_2})\timesφ(p_3^{c_3})\timesφ(p_4^{c_4})\times……\timesφ(p_n^{c_n}) φ(n)=φ(p1c1)×φ(p2c2)×φ(p3c3)×φ(p4c4)×……×φ(pncn)

然后我们再一一来看 p 1 c 1 p_1^{c_1} p1c1 ~ p n c n p_n^{c_n} pncn的欧拉函数值。
欧拉函数求的是有多少个数与代入值互质,那么我们可以换一个思路,就是用所有数的数量减去不与代入值互质的数的数量
对于 p i c i p_i^{c_i} pici来说,因为 p i p_i pi是质数,所以在 1 1 1 ~ p i c i p_i^{c_i} pici中只有是 p i p_i pi的倍数的数不与 p i c i p_i^{c_i} pici互质,那么在 1 1 1 ~ p i c i p_i^{c_i} pici中这样的数有: p i p_i pi p i × 2 p_i\times2 pi×2 p i × 3 p_i\times3 pi×3 p i × 4 … … p_i\times4…… pi×4…… p i × p i c i − 1 p_i\times p_i^{c_i-1} pi×pici1

所以一共有 p i c i − 1 p_i^{c_i-1} pici1个,而 1 1 1 ~ p i c i p_i^{c_i} pici中,一共有 p i c i p_i^{c_i} pici个数,所以 φ ( p i c i ) φ(p_i^{c_i}) φ(pici)的值就是 p i c i − p i c i − 1 p_i^{c_i}-p_i^{c_i-1} picipici1,从中提取一个 p i c i p_i^{c_i} pici就是 p i c i × ( 1 − 1 p i ) p_i^{c_i}\times(1-\frac{1}{p_i}) pici×(1pi1)

接着就是计算 φ ( p 1 c 1 ) × φ ( p 2 c 2 ) × φ ( p 3 c 3 ) × φ ( p 4 c 4 ) × … … × φ ( p n c n ) φ(p_1^{c_1})\timesφ(p_2^{c_2})\timesφ(p_3^{c_3})\timesφ(p_4^{c_4})\times……\timesφ(p_n^{c_n}) φ(p1c1)×φ(p2c2)×φ(p3c3)×φ(p4c4)×……×φ(pncn)

φ ( n ) = p 1 c 1 × ( 1 − 1 p 1 ) × p 2 c 2 × ( 1 − 1 p 2 ) × p 3 c 3 × ( 1 − 1 p 3 ) × … … × p n c n × ( 1 − 1 p n ) φ(n) = p_1^{c_1}\times(1-\frac{1}{p_1})\times p_2^{c_2}\times(1-\frac{1}{p_2})\times p_3^{c_3}\times(1-\frac{1}{p_3})\times ……\times p_n^{c_n}\times(1-\frac{1}{p_n}) φ(n)=p1c1×(1p11)×p2c2×(1p21)×p3c3×(1p31)×……×pncn×(1pn1)

由于 n = p 1 c 1 × p 2 c 2 × p 3 c 3 × … … × p n c n n=p_1^{c_1}\times p_2^{c_2}\times p_3^{c_3}\times……\times p_n^{c_n} n=p1c1×p2c2×p3c3×……×pncn

所以 φ ( n ) = n × ( 1 − 1 p 1 ) × ( 1 − 1 p 2 ) × ( 1 − 1 p 3 ) × … … × ( 1 − 1 p n ) φ(n)=n\times(1-\frac{1}{p_1})\times(1-\frac{1}{p_2})\times(1-\frac{1}{p_3})\times……\times(1-\frac{1}{p_n}) φ(n)=n×(1p11)×(1p21)×(1p31)×……×(1pn1)

( 1 − 1 p i ) (1-\frac{1}{p_i}) (1pi1)稍作化简就可以得到 φ ( n ) = n × p 1 − 1 p 1 × p 2 − 1 p 2 × … … × p m − 1 p m φ(n)=n\times\frac{p_1-1}{p_1}\times\frac{p_2-1}{p_2}\times……\times\frac{p_m-1}{p_m} φ(n)=n×p1p11×p2p21×……×pmpm1

可以用 O ( n ) O(\sqrt n) O(n )的时间复杂度算出一个数的欧拉函数值。

int Euler_function(int n){
	int ans=n;
	for(int i=2;i<=sqrt(n);i++){
		if(n%i==0)ans=ans/i*(i-1);
		while(n%i==0)n/=i;
	}
	if(n>1)ans=ans/n*(n-1);
	return ans;
}

然后可以用 O ( n log ⁡ n ) O(n\log n) O(nlogn)的时间复杂度算出 2 2 2 ~ n n n的欧拉函数值。

void Euler(int n) {
	for(int i=2;i<=n;i++)phi[i]=i;
	for(int i=2;i<=n;i++)
		if(phi[i]==i)
			for(int j=i;j<=n;j+=i)
				phi[j]=phi[j]/i*(i-1);
}

函数性质

  1. ∀ n > 1 \forall n>1 n>1 1 1 1~ n n n 中与 n n n 互质的数之和为 n × φ ( n ) / 2 n\times φ(n)/2 n×φ(n)/2
  2. a , b a,b a,b 互质,则 φ ( a b ) = φ ( a ) φ ( b ) φ(ab)=φ(a)φ(b) φ(ab)=φ(a)φ(b);(积性函数)
  3. p p p 为质数,若 p ∣ n p\mid n pn p 2 ∣ n p^2\mid n p2n,则 φ ( n ) = φ ( n / p ) ∗ p φ(n)=φ(n/p)*p φ(n)=φ(n/p)p
  4. p p p 为质数,若 p ∣ n p\mid n pn p 2 ∤ n p^2\nmid n p2n,则 φ ( n ) = φ ( n / p ) ∗ ( p − 1 ) φ(n)=φ(n/p)*(p-1) φ(n)=φ(n/p)(p1)
  5. ∑ d ∣ n φ ( d ) = n \sum_{d\mid n}φ(d)=n dnφ(d)=n

线性筛法

知道了函数性质,就可以考虑用更优的筛法。

线性筛
void Euler(int n) {
	for(int i=2;i<=n;i++){
		if(!vis[i]){//质数情况
			p[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;i*p[j]<=n;j++) {
			vis[i*p[j]]=1;
			if(i%p[j]==0){
				phi[i*p[j]]=phi[i]*p[j];//性质3
				break;
			}
			else phi[i*p[j]]=phi[i]*(p[j]-1);//性质4
		}
	}
}

例题1

Farey Sequence
这道题可以先前置求好 1 1 1 ~ 1 0 6 10^6 106的欧拉函数,询问时就是求 1 1 1 ~ n n n的函数值之和就行了。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x<10){putchar(x+'0');return;}
	print(x/10);
	putchar(x%10+'0');
}
int n;
int vis[N];
int phi[N];
int p[N];
int cnt;
signed main(){
	for(int i=2;i<N;i++){
		if(!vis[i]){
			p[++cnt]=i;
			phi[i]=i-1;
		}
		for(int j=1;i*p[j]<N;j++){
			vis[i*p[j]]=1;
			if(i%p[j]==0){
				phi[i*p[j]]=phi[i]*p[j];
				break;
			}
			else phi[i*p[j]]=phi[i]*(p[j]-1);
		}
	}
	while(1){
		n=read();
		if(!n)break;
		int ans=0;
		for(int i=1;i<=n;i++)ans+=phi[i];
		print(ans);
		putchar('\n');
	}
}

例题2

Calculation 2
由性质1可以算出 1 1 1 ~ n n n的欧拉函数值之和,也就是 1 1 1 ~ n n n中所有与 n n n互质的数之和,用 1 1 1 ~ n n n的所有数之和减去它就行了。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1000000007;
int read(){
	int x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x*f;
}
void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x<10){putchar(x+'0');return;}
	print(x/10);
	putchar(x%10+'0');
}
int n;
int Sqrt(int res){
	int x=sqrt(res);
	while((x+1)*(x+1)<=res)x++;
	while(x*x>res)x--;
	return x;
}
int oula(int x){
	int res=x%mod;
	for(int i=2;i<=Sqrt(x);i++){
		if(x%i)continue;
		res=res/i%mod*(i-1)%mod;
		while(x%i==0)x/=i;
	}
	if(x>1)res=res/x%mod*(x-1)%mod;
	return res;
}
signed main(){
	while(1){
		n=read();
		if(!n)break;
		print((n-1-oula(n))*n/2%mod);
		putchar('\n');
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值