欧拉函数
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;
}