欧拉函数
定义:
从 1 1 1~ n n n中与 n n n互质的数的个数, a , b a,b a,b互质即 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1
公式:
N
=
p
1
φ
1
∗
p
2
φ
2
∗
.
.
.
.
.
.
∗
p
k
φ
k
N=p_1^{\varphi 1}*p_2^{\varphi 2}*......*p_k^{\varphi k}
N=p1φ1∗p2φ2∗......∗pkφk
φ
(
n
)
=
N
∗
(
1
−
1
p
1
)
∗
(
1
−
1
p
2
)
∗
.
.
.
.
.
.
∗
(
1
−
1
p
k
)
\varphi (n)=N*(1-\frac{1}{p_1})*(1-\frac{1}{p_2})*......*(1-\frac{1}{p_k})
φ(n)=N∗(1−p11)∗(1−p21)∗......∗(1−pk1)
证明:基于容斥原理,详细太复杂可看别的博客
复杂度:
单次 n \sqrt n n,可线性求1-n的欧拉函数
应用:
欧拉定理:
若
a
a
a与
n
n
n互质,则
a
φ
(
n
)
≡
1
(
m
o
d
n
)
a^{\varphi (n)} \equiv 1 (\mod n)
aφ(n)≡1(modn)
推论(费马定理):
若p为质数时
a
φ
(
p
)
≡
1
(
m
o
d
p
)
a^{\varphi (p)} \equiv 1 (\mod p)
aφ(p)≡1(modp)
a
p
−
1
≡
1
(
m
o
d
p
)
a^{p-1 } \equiv 1(\mod p)
ap−1≡1(modp)
板子:
//单次
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;cin>>t;while(t--){
int n;
cin>>n;
int res=n;
for(int i=2;i<=n/i;i++){
if(n%i==0){
res=res/i*(i-1);
while(n%i==0) n/=i;
}
}
if(n>1) res=res/n*(n-1);
cout<<res<<endl;
}
}
//线性求1-n的欧拉函数
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int primes[N], cnt; // primes[]存储所有素数
int euler[N]; // 存储每个数的欧拉函数
bool st[N]; // st[x]存储x是否被筛掉(合数标记)
void get_eulers(int n)
{
euler[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
// 质数
primes[cnt ++ ] = i;
euler[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j ++ )
{
int t = primes[j] * i;
st[t] = true;
if (i % primes[j] == 0)
{
euler[t] = euler[i] * primes[j];
break;
}
euler[t] = euler[i] * (primes[j] - 1);
}
}
}
int main(int argc, char const *argv[]) {
get_eulers(1e6);
int n;
cin>>n;
long long res=0;
for(int i=1;i<=n;i++){
res+=euler[i];
}
cout<<res<<endl;
return 0;
}