数学知识——欧拉函数
欧拉函数
1 ∼ N 1∼N 1∼N 中与 N N N互质的数的个数被称为欧拉函数,记为 ϕ ( N ) \phi(N) ϕ(N)。
欧拉函数
对于
N
=
p
1
α
1
p
2
α
2
p
3
α
3
.
.
.
p
k
α
k
N=p_1^{\alpha_1}p_2^{\alpha_2}p_3^{\alpha_3}...p_k^{\alpha_k}
N=p1α1p2α2p3α3...pkαk,有
ϕ
(
N
)
=
N
×
p
1
−
1
p
1
×
p
2
−
1
p
2
.
.
.
×
p
k
−
1
p
k
\phi(N)=N×\frac{p_1-1}{p_1}×\frac{p_2-1}{p_2}...×\frac{p_k-1}{p_k}
ϕ(N)=N×p1p1−1×p2p2−1...×pkpk−1
证明:
根据容斥原理,与
N
N
N互质的数的个数为
N
−
N
p
1
−
N
p
2
−
N
p
3
.
.
.
+
N
p
1
p
2
+
N
p
1
p
3
+
.
.
.
−
N
p
1
p
2
p
3
−
N
p
1
p
2
p
4
−
.
.
.
N-\frac{N}{p_1}-\frac{N}{p_2}-\frac{N}{p_3}...+\frac{N}{p_1p_2}+\frac{N}{p_1p_3}+...-\frac{N}{p_1p_2p_3}-\frac{N}{p_1p_2p_4}-...
N−p1N−p2N−p3N...+p1p2N+p1p3N+...−p1p2p3N−p1p2p4N−...
其中每一项都含有
N
N
N,可以把
N
N
N提出,含有
p
i
p_i
pi数为奇数的项前符号为
−
-
−,为偶数的项前面的符号为
+
+
+,即上式可以化简为
N
(
1
−
1
p
1
)
(
1
−
1
p
2
)
.
.
.
(
1
−
1
p
k
)
N(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k})
N(1−p11)(1−p21)...(1−pk1)。
时间复杂度为
O
(
N
)
O(\sqrt N)
O(N)
for (int i = 2; i <= a / i; i ++ )
{
if (a % i == 0)
{
while (a % i == 0) a /= i;
res = res * (i - 1) / i;
}
}
if (a > 1) res = res * (a - 1) / a;
cout << res << endl;
筛法求欧拉函数
我们可以在线性筛的基础上完成欧拉函数的求解。
1.
ϕ
(
1
)
=
1
\phi(1)=1
ϕ(1)=1
2.如果一个数
N
N
N是质数,那么
ϕ
(
N
)
=
N
−
1
\phi(N)=N-1
ϕ(N)=N−1。
3.
ϕ
(
p
r
i
m
e
s
[
j
]
∗
i
)
\phi(primes[j]*i)
ϕ(primes[j]∗i)分两种情况:
(1).
i
%
p
r
i
m
e
s
[
j
]
=
=
0
i\%primes[j]==0
i%primes[j]==0时,
p
r
i
m
e
s
[
j
]
primes[j]
primes[j]是
i
i
i的最小质因子,所以在
ϕ
(
i
)
\phi(i)
ϕ(i)中,
(
1
−
1
p
r
i
m
e
s
[
j
]
)
(1-\frac{1}{primes[j]})
(1−primes[j]1)这一项已经考虑过了,只需要将
N
N
N修正为
p
r
i
m
e
s
[
j
]
primes[j]
primes[j]倍,最终结果为
p
h
i
[
i
]
∗
p
r
i
m
e
s
[
j
]
phi[i] * primes[j]
phi[i]∗primes[j]。
(2).
i
%
p
r
i
m
e
s
[
j
]
!
=
0
i\%primes[j]!=0
i%primes[j]!=0时,
p
r
i
m
e
s
[
j
]
primes[j]
primes[j]不是
i
i
i的质因子,只是
p
r
i
m
e
s
[
j
]
∗
i
primes[j] * i
primes[j]∗i的最小质因子,因此不仅需要将基数
N
N
N修正为
p
r
i
m
e
s
[
j
]
primes[j]
primes[j]倍,还需要补上
1
−
1
/
p
r
i
m
e
s
[
j
]
1 - 1 / primes[j]
1−1/primes[j]这一项,因此最终结果
p
h
i
[
i
]
∗
(
p
r
i
m
e
s
[
j
]
−
1
)
phi[i] * (primes[j] - 1)
phi[i]∗(primes[j]−1)。
void get_eulers(int n)
{
phi[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!st[i])
{
primes[cnt++] = i;
phi[i] = i - 1;
}
for (int j = 0; primes[j] <= n / i; j++)
{
st[primes[j] * i] = true;
if (i % primes[j] == 0)
{
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);
}
}
}
可见的点
在一个平面直角坐标系的第一象限内,如果一个点 ( x , y ) (x,y) (x,y) 与原点 ( 0 , 0 ) (0,0) (0,0) 的连线中没有通过其他任何点,则称该点在原点处是可见的。
例如,点 ( 4 , 2 ) (4,2) (4,2) 就是不可见的,因为它与原点的连线会通过点 ( 2 , 1 ) (2,1) (2,1)。
部分可见点与原点的连线如下图所示:
编写一个程序,计算给定整数 N N N 的情况下,满足 0 ≤ x , y ≤ N 0≤x,y≤N 0≤x,y≤N 的可见点 ( x , y ) (x,y) (x,y) 的数量(可见点不包括原点)。
输入格式
第一行包含整数
C
C
C,表示共有
C
C
C 组测试数据。
每组测试数据占一行,包含一个整数 N N N。
输出格式
每组测试数据的输出占据一行。
应包括:测试数据的编号(从 1 开始),该组测试数据对应的 N 以及可见点的数量。
同行数据之间用空格隔开。
数据范围
1
≤
N
,
C
≤
1000
1≤N,C≤1000
1≤N,C≤1000
输入样例:
4
2
4
5
231
输出样例:
1 2 5
2 4 13
3 5 21
4 231 32549
如果所有的点与原点的连接构成直线 y = a b x y=\frac{a}{b}x y=bax的话,本题要求的就是在1到n范围内互质的(a,b)的对数是多少,按照y=x分成上下两部分,本题的答案即为 2 ∗ ϕ ( n ) + 1 2*\phi(n)+1 2∗ϕ(n)+1。
#include <iostream>
using namespace std;
const int N = 1010;
int primes[N], phi[N];
bool st[N];
int n, m, cnt;
void init(int n)
{
phi[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
phi[i] = i - 1;
primes[cnt ++ ] = i;
}
for (int j = 0; primes[j] * i <= n; j ++ )
{
st[primes[j] * i] = 1;
if (i % primes[j] == 0)
{
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);
}
}
return ;
}
int main()
{
init(N - 1);
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> m;
int res = 1;
for (int j = 1; j <= m; j ++ ) res += phi[j] * 2;
cout << i << " " << m << " " << res << endl;
}
return 0;
}
最大公约数
给定整数 N N N,求 1 ≤ x , y ≤ N 1≤x,y≤N 1≤x,y≤N 且 G C D ( x , y ) GCD(x,y) GCD(x,y) 为素数的数对 ( x , y ) (x,y) (x,y) 有多少对。
G C D ( x , y ) GCD(x,y) GCD(x,y) 即求 x , y x,y x,y 的最大公约数。
输入格式
输入一个整数 N N N。
输出格式
输出一个整数,表示满足条件的数对数量。
数据范围
1
≤
N
≤
1
0
7
1≤N≤10^7
1≤N≤107
输入样例:
4
输出样例:
4
G C D ( x , y ) = p , GCD(x,y)=p, GCD(x,y)=p,
G C D ( x / p , y / p ) = 1 GCD(x/p,y/p)=1 GCD(x/p,y/p)=1,
x ′ = x / p , y ′ = y / p x'=x/p,y'=y/p x′=x/p,y′=y/p
1 ≤ x ′ , y ′ ≤ N / p 1\leq x',y'\leq N/p 1≤x′,y′≤N/p
本题可以转换为对于每一个 p p p,在 N / p N/p N/p范围内找互质的数的对数再求和。
答案为 ∑ i = 1 m a x p ∑ j = 1 i 2 ∗ ϕ ( j ) − 1 \sum_{i=1}^{maxp} \sum_{j=1}^{i}2*\phi(j)-1 ∑i=1maxp∑j=1i2∗ϕ(j)−1
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e7 + 10;
bool st[N];
int primes[N], cnt;
int phi[N];
ll s[N];
ll res;
int n;
void init(int n)
{
s[1] = 1;
for (int i = 2; i <= n; i ++ )
{
if (!st[i])
{
phi[i] = i - 1;
primes[cnt ++ ] = i;
}
for (int j = 0; primes[j] * i <= n; j ++ )
{
st[primes[j] * i] = 1;
if (i % primes[j] == 0)
{
phi[i * primes[j]] = phi[i] * primes[j];
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);
}
}
for (int i = 2; i <= n; i ++ ) s[i] = s[i - 1] + phi[i];
}
int main()
{
cin >> n;
init(n);
for (int i = 0; i < cnt; i ++ )
res += 2 * s[n / primes[i]] - 1;
cout << res << endl;
return 0;
}