函数作用
计算 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×p1p1−1×p2p2−1×……×pmpm−1
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×pici−1
所以一共有 p i c i − 1 p_i^{c_i-1} pici−1个,而 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} pici−pici−1,从中提取一个 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×(1−pi1)
接着就是计算 φ ( 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×(1−p11)×p2c2×(1−p21)×p3c3×(1−p31)×……×pncn×(1−pn1)
由于 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×(1−p11)×(1−p21)×(1−p31)×……×(1−pn1)
将 ( 1 − 1 p i ) (1-\frac{1}{p_i}) (1−pi1)稍作化简就可以得到 φ ( 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×p1p1−1×p2p2−1×……×pmpm−1
可以用 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);
}
函数性质
- ∀ 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;
- 若 a , b a,b a,b 互质,则 φ ( a b ) = φ ( a ) φ ( b ) φ(ab)=φ(a)φ(b) φ(ab)=φ(a)φ(b);(积性函数)
- 设 p p p 为质数,若 p ∣ n p\mid n p∣n 且 p 2 ∣ n p^2\mid n p2∣n,则 φ ( n ) = φ ( n / p ) ∗ p φ(n)=φ(n/p)*p φ(n)=φ(n/p)∗p;
- 设 p p p 为质数,若 p ∣ n p\mid n p∣n 且 p 2 ∤ n p^2\nmid n p2∤n,则 φ ( n ) = φ ( n / p ) ∗ ( p − 1 ) φ(n)=φ(n/p)*(p-1) φ(n)=φ(n/p)∗(p−1);
- ∑ d ∣ n φ ( d ) = n \sum_{d\mid n}φ(d)=n ∑d∣nφ(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');
}
}