欧拉函数
对于正整数 n n n ,欧拉函数 φ ( n ) \varphi(n) φ ( n ) 代表小于 n n n 的数中,所有与 n n n 互质的数的个数。一般认为 φ ( 1 ) = 1 \varphi(1) = 1 φ ( 1 ) = 1 。
性质1
对于素数 p p p ,1 ∼ ( p − 1 ) 1\sim (p-1) 1 ∼ ( p − 1 ) 都与其互质,所以 φ ( p ) = p − 1 \varphi(p)=p-1 φ ( p ) = p − 1 。
性质2
对于互质的 m , n m,n m , n 有 φ ( m n ) = φ ( m ) φ ( n ) \varphi(mn)=\varphi(m)\varphi(n) φ ( mn ) = φ ( m ) φ ( n ) ,即欧拉函数为非完全积性函数。
这个证明需要剩余系的复合,我不太会,可以参考 OI-WIKI。
性质3
对于素数 p p p ,有 φ ( p k ) = p k − p k − 1 \varphi(p^k)=p^k-p^{k-1} φ ( p k ) = p k − p k − 1 。
证明:小于 p k p^k p k 的所有数字中,只有 1 p , 2 p , … , ( p k − 1 − 1 ) p 1p,2p,\dots,(p^{k-1}-1)p 1 p , 2 p , … , ( p k − 1 − 1 ) p 共 p k − 1 − 1 p^{k-1}-1 p k − 1 − 1 个数与 p k p^k p k 不互质,一共有 p k − 1 p^{k}-1 p k − 1 个数,故 φ ( p k ) = p k − 1 − ( p k − 1 − 1 ) = p k − p k − 1 \varphi(p^k)=p^{k}-1-(p^{k-1}-1)=p^k-p^{k-1} φ ( p k ) = p k − 1 − ( p k − 1 − 1 ) = p k − p k − 1 。
性质4
对于任意正整数 n n n ,将其质因数分解为 n = ∏ i = 1 k p i c i n=\prod_{i=1}^k p_i^{c_i} n = ∏ i = 1 k p i c i ,有:
φ ( n ) = φ ( ∏ i = 1 k p i c i ) = ∏ i = 1 k φ ( p i c i ) = ∏ i = 1 k p i c i ( 1 − 1 p i ) = n ∏ i = 1 k ( 1 − 1 p i ) \begin{aligned}
\varphi(n)&=\varphi\left(\prod_{i=1}^k p_i^{c_i}\right)\\
&=\prod_{i=1}^k \varphi(p_i^{c_i})\\
&=\prod_{i=1}^k p_i^{c_i}(1-\frac{1}{p_i})\\
&=n\prod_{i=1}^k (1-\frac{1}{p_i})
\end{aligned}
φ ( n ) = φ ( i = 1 ∏ k p i c i ) = i = 1 ∏ k φ ( p i c i ) = i = 1 ∏ k p i c i ( 1 − p i 1 ) = n i = 1 ∏ k ( 1 − p i 1 )
这是也是欧拉函数的一种求法。
性质5
对于欧拉函数,有下面这个常见的式子:
∑ d ∣ n φ ( d ) = n \sum_{d|n}\varphi(d)=n
d ∣ n ∑ φ ( d ) = n
证明:设 f ( n ) = ∑ d ∣ n φ ( d ) f(n)=\sum_{d|n}\varphi(d) f ( n ) = ∑ d ∣ n φ ( d ) ,可以证明 f ( n ) f(n) f ( n ) 为积性函数,设 n , m n,m n , m 互质则显然 n , m n,m n , m 的任何一个因子 i , j i,j i , j 也是互质的:
f ( n ) f ( m ) = ∑ i ∣ n ∑ j ∣ m φ ( i ) φ ( j ) = ∑ i ∣ n ∑ j ∣ m φ ( i j ) = ∑ d ∣ n m φ ( d ) = f ( n m ) \begin{aligned}
f(n)f(m)&=\sum_{i|n}\sum_{j|m}\varphi(i)\varphi(j)\\
&=\sum_{i|n}\sum_{j|m}\varphi(ij)\\
&=\sum_{d|nm}\varphi(d)\\
&=f(nm)
\end{aligned}
f ( n ) f ( m ) = i ∣ n ∑ j ∣ m ∑ φ ( i ) φ ( j ) = i ∣ n ∑ j ∣ m ∑ φ ( ij ) = d ∣ nm ∑ φ ( d ) = f ( nm )
对 n n n 进行质因数分解,所以 f ( n ) = f ( p c 1 ) f ( p c 2 ) … f ( p c k ) f(n)=f(p^{c_1})f(p^{c_2})\dots f(p^{c_k}) f ( n ) = f ( p c 1 ) f ( p c 2 ) … f ( p c k ) ,又有:
f ( p c ) = ∑ i = 0 c φ ( p i ) = 1 + ∑ i = 1 c ( p i − p i − 1 ) = p c \begin{aligned}
f(p^c)&=\sum_{i=0}^c \varphi(p^i)\\
&=1+\sum_{i=1}^c (p^i-p^{i-1})\\
&=p^c
\end{aligned}
f ( p c ) = i = 0 ∑ c φ ( p i ) = 1 + i = 1 ∑ c ( p i − p i − 1 ) = p c
因此 f ( n ) = n f(n)=n f ( n ) = n ,得证。
分解质因数求值
复杂度为 O ( n log n ) O(\sqrt n\log n) O ( n log n ) ,其中 log n \log n log n 是指质因数分解后的 n n n 的所有质数的指数之和,实际肯定是远小于 log n \log n log n 的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int phi (int n) { int res = n; for (int i = 2 ; i <= n/i; i++) { if (n % i == 0 ) { res = res - res/i; while (n % i == 0 ) n /= i; } } if (n > 1 ) res = res-res/n; return res; }
这里你可能会对 i 2 ≤ n i^2\le n i 2 ≤ n 这个循环条件存在疑问,因为 n n n 随着循环是在变化的。首先 i 2 ≤ n i^2\le n i 2 ≤ n 等价于 i ≤ n / i i\le n/i i ≤ n / i ,然后 i i i 是整数,所以等价于 i ≤ ⌊ n / i ⌋ i\le \lfloor n/i\rfloor i ≤ ⌊ n / i ⌋ 。
这里设当前 n = p i p j n=p_ip_j n = p i p j ,其中 p i ≤ p j p_i\le p_j p i ≤ p j ,那么因为还没有除掉 p i p_i p i ,所以 i ≤ p i i\le p_i i ≤ p i 是成立的,因此 i 2 ≤ p i p j = n i^2\le p_ip_j=n i 2 ≤ p i p j = n ;所以只要 n n n 还有多于两个未除掉的质因数,就不会结束循环。
线性筛法求值
复杂度同线性筛,为 O ( n ) O(n) O ( n ) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int phi[N], primes[N], cntp;bitset<N> st; void init (int n) { phi[1 ] = 1 ; for (int i = 2 ; i <= n; i++) { if (!st[i]) primes[cntp++] = i, phi[i] = i-1 ; for (int j = 0 ; primes[j] <= n/i; j++) { st[i*primes[j]] = 1 ; if (i % primes[j]) phi[i*primes[j]] = phi[i] * phi[primes[j]]; else { phi[i*primes[j]] = phi[i] * primes[j]; break ; } } } }
可以证明当要求 i ⋅ p j i\cdot p_j i ⋅ p j 的时候,φ ( i ) \varphi(i) φ ( i ) 一定已经求出来了:
如果 i i i 是质数,那么它会在进入内层 for
循环前被求出来。
如果 i i i 是合数,那么它会在 i i i 循环到自己之前就被筛掉,筛掉的同时也就求出来了 φ ( i ) \varphi(i) φ ( i ) 。
接下来说明递推式:
如果 i i i 是质数,那么在 1 ∼ i − 1 1 \sim i-1 1 ∼ i − 1 中所有数都与它互质,所以有 φ ( i ) = i − 1 \varphi(i)=i-1 φ ( i ) = i − 1 。
如果 i m o d p j = 0 i \bmod p_j=0 i mod p j = 0 ,此时 p j p_j p j 是 i i i 的最小质因数,由欧拉函数的解析式知,φ ( p j × i ) = p j φ ( i ) \varphi(p_j\times i)=p_j\varphi(i) φ ( p j × i ) = p j φ ( i ) 。
如果 i m o d p j ≠ 0 i\bmod p_j\ne 0 i mod p j = 0 ,此时 p j p_j p j 不是 i i i 的质因数,那么 φ ( p j ⋅ i ) = φ ( p j ) φ ( i ) \varphi(p_j\cdot i)=\varphi(p_j)\varphi(i) φ ( p j ⋅ i ) = φ ( p j ) φ ( i ) 。
欧拉定理
欧拉定理:若 a a a 与 x x x 互质,则 a φ ( x ) ≡ 1 ( m o d x ) a^{\varphi(x)}\equiv 1 \pmod x a φ ( x ) ≡ 1 ( mod x ) 。
证明:设所有小于 x x x 的数中所有与 x x x 互质的数是 x 1 , x 2 , ⋯ , x φ ( x ) x_1, x_2, \cdots, x_{\varphi(x)} x 1 , x 2 , ⋯ , x φ ( x ) ,那么 a x 1 , a x 2 , ⋯ , a x φ ( x ) ax_1, ax_2, \cdots, ax_{\varphi(x)} a x 1 , a x 2 , ⋯ , a x φ ( x ) 也与 x x x 互质(无论是 a a a 还是 x i x_i x i 都与 x x x 没有相同的质因数,所以 a x i ax_i a x i 也与 x x x 没有相同的质因数)。
并且 a x 1 , a x 2 , ⋯ , a x φ ( x ) ax_1, ax_2, \cdots, ax_{\varphi(x)} a x 1 , a x 2 , ⋯ , a x φ ( x ) 对 x x x 取模两两不相同,这步用反证法证明,假设 a x i ≡ a x j ( m o d x ) ax_i\equiv ax_j\pmod x a x i ≡ a x j ( mod x ) 由于 gcd ( a , x ) = 1 \gcd(a,x)=1 g cd( a , x ) = 1 有 x i ≡ x j ( m o d x ) x_i\equiv x_j\pmod x x i ≡ x j ( mod x ) 这是矛盾的。
于是这两组数模 x x x 之后其实是同一组数据,那么它们取模之后全部乘起来结果是相同的。
∏ i = 1 φ ( x ) ( a x i ) ≡ ∏ i = 1 φ ( x ) x i ( m o d x ) a φ ( x ) ∏ i = 1 φ ( x ) x i ≡ ∏ i = 1 φ ( x ) x i ( m o d x ) \begin{aligned}
\prod_{i=1}^{\varphi(x)}(ax_i)&\equiv\prod_{i=1}^{\varphi(x)}x_i\pmod x\\
a^{\varphi(x)}\prod_{i=1}^{\varphi(x)}x_i&\equiv \prod_{i=1}^{\varphi(x)}x_i \pmod x\\
\end{aligned}
i = 1 ∏ φ ( x ) ( a x i ) a φ ( x ) i = 1 ∏ φ ( x ) x i ≡ i = 1 ∏ φ ( x ) x i ( mod x ) ≡ i = 1 ∏ φ ( x ) x i ( mod x )
由于任意一个 x i x_i x i 都与 x x x 互质,所以它们的乘积也与 x x x 互质,所以 a φ ( x ) ≡ 1 ( m o d x ) a^{\varphi(x)}\equiv 1\pmod x a φ ( x ) ≡ 1 ( mod x ) 。
特别地,如果设 p p p 是质数,那么 a φ ( p ) ≡ a p − 1 ≡ 1 ( m o d p ) a^{\varphi(p)}\equiv a^{p-1} \equiv 1\pmod p a φ ( p ) ≡ a p − 1 ≡ 1 ( mod p ) ,欧拉定理是费马小定理的拓展。
拓展欧拉定理
给定 a , m , b a,m,b a , m , b 求 a b m o d m a^b \bmod m a b mod m ,其中 1 ≤ a ≤ 1 0 9 , 1 ≤ b ≤ 1 0 20000000 , 1 ≤ m ≤ 1 0 8 1\le a\le 10^9,1\le b\le10^{20000000},1\le m\le 10^8 1 ≤ a ≤ 1 0 9 , 1 ≤ b ≤ 1 0 20000000 , 1 ≤ m ≤ 1 0 8 。
不要求 a , m a,m a , m 互质,且 b ≥ φ ( m ) b\ge \varphi(m) b ≥ φ ( m ) 时满足 a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d m ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\pmod m a b ≡ a b mod φ ( m ) + φ ( m ) ( mod m ) ,这也是降幂公式。
引理1
如果 gcd ( m 1 , m 2 ) = 1 \gcd(m_1,m_2)=1 g cd( m 1 , m 2 ) = 1 时, x ≡ y ( m o d m 1 ) , x ≡ y ( m o d m 2 ) x\equiv y\pmod {m_1},x\equiv y\pmod{m_2} x ≡ y ( mod m 1 ) , x ≡ y ( mod m 2 ) 那么一定有 x − y ≡ 0 ( m o d m 1 m 2 ) x-y\equiv 0\pmod {m_1m_2} x − y ≡ 0 ( mod m 1 m 2 ) 。
证明:x − y x-y x − y 是 m 1 , m 2 m_1,m_2 m 1 , m 2 的公倍数,所以 x − y ≡ 0 ( m o d m 1 m 2 ) x-y\equiv 0\pmod {m_1m_2} x − y ≡ 0 ( mod m 1 m 2 )
引理2
若 p p p 为质数,那么 φ ( p k ) = p k ( 1 − 1 p ) = p k − 1 ( p − 1 ) \varphi(p^k)=p^k(1-\frac{1}{p})=p^{k-1}(p-1) φ ( p k ) = p k ( 1 − p 1 ) = p k − 1 ( p − 1 ) ,有 φ ( p k ) ≥ k \varphi(p^k)\ge k φ ( p k ) ≥ k
证明:如果固定 k k k ,那么 φ ( p k ) \varphi(p^k) φ ( p k ) 是对 p p p 单调递增的,因为是两个单调递增的恒正的函数相乘。
因此,φ ( p k ) ≥ φ ( 2 k ) = 2 k − 1 ≥ k \varphi(p^k)\ge \varphi(2^k)= 2^{k-1}\ge k φ ( p k ) ≥ φ ( 2 k ) = 2 k − 1 ≥ k ,关于最后一个不等式,我们可以构造函数 f ( x ) = 2 x − 1 − x f(x)=2^{x-1}-x f ( x ) = 2 x − 1 − x 研究。
f ( x ) = 2 x − 1 − x f ′ ( x ) = 2 x − 1 ln 2 − 1 , f ′ ( x ) ↗ f ′ ( x 0 ) = 0 ⇒ x 0 = log 2 log 2 e + 1 ∈ ( 1 , 2 ) f ( 1 ) = f ( 2 ) = 0 ∴ f ( x ) ≥ 0 , x ∈ N ∗ \begin{aligned}
f(x)&=2^{x-1}-x\\
f'(x)&=2^{x-1}\ln 2-1,f'(x)\nearrow \\
f'(x_0)&=0\Rightarrow x_0=\log_2\log_2 e+1\in(1,2)\\
f(1)&=f(2)=0\\
\therefore f(x)&\ge 0,x\in \N^*
\end{aligned}
f ( x ) f ′ ( x ) f ′ ( x 0 ) f ( 1 ) ∴ f ( x ) = 2 x − 1 − x = 2 x − 1 ln 2 − 1 , f ′ ( x ) ↗ = 0 ⇒ x 0 = log 2 log 2 e + 1 ∈ ( 1 , 2 ) = f ( 2 ) = 0 ≥ 0 , x ∈ N ∗
证毕。
定理
首先,gcd ( a , m ) = 1 \gcd(a,m)=1 g cd( a , m ) = 1 时,有 a φ ( m ) ≡ 1 ( m o d m ) a^{\varphi(m)}\equiv 1\pmod m a φ ( m ) ≡ 1 ( mod m ) ,那么 a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d m ) a^{b}\equiv a^{b\bmod\varphi(m)+\varphi(m)}\pmod m a b ≡ a b mod φ ( m ) + φ ( m ) ( mod m ) 显然成立。主要证明 gcd ( a , m ) ≠ 1 \gcd(a,m)\ne 1 g cd( a , m ) = 1 时的情况。
将 m m m 分解质因数,只需要证明 a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d p 1 k 1 , p 2 k 2 , ⋯ ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\pmod {p_1^{k_1},p_2^{k_2},\cdots} a b ≡ a b mod φ ( m ) + φ ( m ) ( mod p 1 k 1 , p 2 k 2 , ⋯ ) 即可。
当 gcd ( a , p k ) = 1 \gcd(a,p^{k})=1 g cd( a , p k ) = 1 时,由于欧拉函数是积性函数,那么 φ ( p k ) ∣ φ ( m ) \varphi(p^k)|\varphi(m) φ ( p k ) ∣ φ ( m ) :
a b m o d φ ( m ) + φ ( m ) ≡ a b − k φ ( m ) + φ ( m ) ≡ a b − k ′ φ ( p k ) + φ ( p k ) ≡ a b ( m o d p k ) \begin{aligned}
a^{b\bmod \varphi(m)+\varphi(m)}&\equiv a^{b-k\varphi(m)+\varphi(m)}\\
&\equiv a^{b-k'\varphi(p^k)+\varphi(p^k)}\\
&\equiv a^b \pmod {p^k}
\end{aligned}
a b mod φ ( m ) + φ ( m ) ≡ a b − k φ ( m ) + φ ( m ) ≡ a b − k ′ φ ( p k ) + φ ( p k ) ≡ a b ( mod p k )
最后一步直接套用上面已经讨论过的情况。
当 gcd ( a , p k ) ≠ 1 \gcd(a,p^k)\ne 1 g cd( a , p k ) = 1 时,有 p ∣ a p|a p ∣ a ,设 a = n p a=np a = n p ,由于需要保证 b ≥ φ ( m ) b\ge \varphi(m) b ≥ φ ( m ) ,并且 φ ( m ) ≥ φ ( p k ) ≥ k \varphi(m)\ge \varphi(p^k)\ge k φ ( m ) ≥ φ ( p k ) ≥ k 那么有:
a b ≡ n b p b ≡ n b p b − k p k ≡ 0 ( m o d p k ) a b m o d φ ( m ) + φ ( m ) ≡ n b m o d φ ( m ) + φ ( m ) p b m o d φ ( m ) + φ ( m ) − k p k ≡ 0 ( m o d p k ) a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d p k ) \begin{aligned}
a^b&\equiv n^bp^b\equiv n^bp^{b-k}p^k\equiv 0\pmod {p^k}\\
a^{b\bmod \varphi(m)+\varphi(m)}&\equiv n^{b\bmod \varphi(m)+\varphi(m)}p^{b\bmod \varphi(m)+\varphi(m)-k}p^k \equiv 0\pmod {p^k}\\
a^b&\equiv a^{b\bmod \varphi(m)+\varphi(m)} \pmod{p^k}
\end{aligned}
a b a b mod φ ( m ) + φ ( m ) a b ≡ n b p b ≡ n b p b − k p k ≡ 0 ( mod p k ) ≡ n b mod φ ( m ) + φ ( m ) p b mod φ ( m ) + φ ( m ) − k p k ≡ 0 ( mod p k ) ≡ a b mod φ ( m ) + φ ( m ) ( mod p k )
综上,a b ≡ a b m o d φ ( m ) + φ ( m ) ( m o d m ) , b ≥ φ ( m ) a^b\equiv a^{b\bmod \varphi(m)+\varphi(m)}\pmod{m},b\ge \varphi(m) a b ≡ a b mod φ ( m ) + φ ( m ) ( mod m ) , b ≥ φ ( m ) ,这也被称作降幂公式。
代码
对 b b b 边读边取模即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <bits/stdc++.h> using namespace std;int a, m, b;int phi;int euler (int m) { int res = m; for (int i = 2 ; i <= m/i; i++) { bool flag = false ; while (m % i == 0 ) { flag = true ; m /= i; } if (flag) res -= res / i; } if (m > 1 ) res -= res / m; return res; } int read () { char ch = getchar (); while (ch < '0' || ch > '9' ) ch = getchar (); bool flag = false ; int res = 0 ; while ('0' <= ch && ch <= '9' ) { res = res * 10 + (ch ^ 48 ); if (res > phi) { flag = true ; res %= phi; } ch = getchar (); } return res + flag * phi; } int qmi (int a, int k) { int res = 1 ; while (k) { if (k & 1 ) res = 1LL * res * a % m; a = 1LL * a * a % m; k >>= 1 ; } return res; } int main () { scanf ("%d%d" , &a, &m); phi = euler (m); return !printf ("%d\n" , qmi (a, read ())); }
幂塔
定义 a 0 = 1 a_0=1 a 0 = 1 ,a n = 2 a n − 1 a_n=2^{a_{n-1}} a n = 2 a n − 1 ,可以证明 a n m o d p a_n\bmod p a n mod p 在某一项后都是同一个值,求这个值。
输入 T T T 个 p p p ,对每个 p p p 输出指定值,T ≤ 1 0 3 , p ≤ 1 0 7 T\le 10^3, p\le 10^7 T ≤ 1 0 3 , p ≤ 1 0 7 。
题目链接:P4139 。
先套一下拓展欧拉定理公式。
f ( p ) = 2 2 2 ⋯ mod φ ( p ) + φ ( p ) m o d p = 2 f ( φ ( p ) ) + φ ( p ) m o d p \begin{aligned}
f(p)&=2^{2^{2^{\cdots}}\text {mod }\varphi(p)+\varphi(p)}\bmod p\\
&=2^{f(\varphi(p))+\varphi(p)}\bmod p
\end{aligned}
f ( p ) = 2 2 2 ⋯ mod φ ( p ) + φ ( p ) mod p = 2 f ( φ ( p )) + φ ( p ) mod p
不断取 φ ( p ) \varphi(p) φ ( p ) 一定会到达 1 1 1 ,而 f ( 1 ) = 0 f(1)=0 f ( 1 ) = 0 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> using namespace std;const int N = 10000010 ;int phi[N];vector<int > primes; bitset<N> st; void init (int n) { for (int i = 2 ; i <= n; i++) { if (!st[i]) primes.emplace_back (i), phi[i] = i-1 ; for (int j = 0 ; primes[j] <= n/i; j++) { st[i*primes[j]] = 1 ; if (i % primes[j] == 0 ) { phi[i*primes[j]] = primes[j] * phi[i]; break ; } else { phi[i*primes[j]] = (primes[j]-1 ) * phi[i]; } } } } int qmi (int a, int k, int p) { int res = 1 ; while (k) { if (k & 1 ) res = 1LL * res * a % p; a = 1LL * a * a % p; k >>= 1 ; } return res; } int f (int p) { if (p == 1 ) return 0 ; return qmi (2 , f (phi[p])+phi[p], p); } int main () { int T, p; init (N-1 ); scanf ("%d" , &T); while (T--) scanf ("%d" , &p), printf ("%d\n" , f (p)); return 0 ; }
[SDOI2008] 仪仗队
给定正整数 1 ≤ n ≤ 40000 1\le n\le40000 1 ≤ n ≤ 40000 ,求出 ( 0 , 0 ) (0,0) ( 0 , 0 ) 到 ( x , y ) (x,y) ( x , y ) 的所有点中直接相连不经过其它点的所有点的数量。
题目链接:P2158 。
不经过其它点,除了 ( 0 , 1 ) , ( 1 , 0 ) (0,1),(1,0) ( 0 , 1 ) , ( 1 , 0 ) 外,其它点都是 ( x , y ) (x,y) ( x , y ) 且满足 1 ≤ x , y ≤ n − 1 1\le x,y\le n-1 1 ≤ x , y ≤ n − 1 ,所以先 n ← n − 1 n\gets n-1 n ← n − 1 ,然后考虑何为“不经过其它点”。
若 ( 0 , 0 ) (0,0) ( 0 , 0 ) 到 ( x 1 , y 1 ) (x_1,y_1) ( x 1 , y 1 ) 经过 ( x 0 , y 0 ) (x_0,y_0) ( x 0 , y 0 ) ,其中 x 0 < x 1 , y 0 < y 1 x_0<x_1,y_0<y_1 x 0 < x 1 , y 0 < y 1 。那么这个连线,O x Ox O x 轴,x = x 1 , x = x 2 x=x_1,x=x_2 x = x 1 , x = x 2 这四条直线构成的两个三角形存在相似关系,也就是有 y 1 / x 1 = y 0 / x 0 y_1/x_1=y_0/x_0 y 1 / x 1 = y 0 / x 0 ,也就是说 gcd ( x 1 , y 1 ) ≠ 1 \gcd(x_1,y_1) \ne 1 g cd( x 1 , y 1 ) = 1 。
当 gcd ( x 1 , y 1 ) = 1 \gcd(x_1,y_1)=1 g cd( x 1 , y 1 ) = 1 时,则该点满足条件(这是原命题“若 ( x 1 , y 1 ) (x_1,y_1) ( x 1 , y 1 ) 不满足条件,则 gcd ( x 1 , y 1 ) ≠ 1 \gcd(x_1,y_1)\ne 1 g cd( x 1 , y 1 ) = 1 ”的逆否命题)。
所以答案就会是(别忘了 ( 0 , 1 ) , ( 1 , 0 ) (0,1),(1,0) ( 0 , 1 ) , ( 1 , 0 ) 这两个点):
2 + ∑ i = 1 n ∑ j = 1 n [ gcd ( i , j ) = 1 ] 2+\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=1]
2 + i = 1 ∑ n j = 1 ∑ n [ g cd( i , j ) = 1 ]
原式具有对称性,继续化简:
2 + 2 ∑ i = 1 n ∑ j ≤ i [ gcd ( i , j ) = 1 ] − ∑ i = 1 n [ gcd ( i , i ) = 1 ] = 1 + 2 ∑ i = 1 n φ ( i ) 2+2\sum_{i=1}^n\sum_{j\le i}[\gcd(i,j)=1]-\sum_{i=1}^n[\gcd(i,i)=1]=1+2\sum_{i=1}^n\varphi(i)\\
2 + 2 i = 1 ∑ n j ≤ i ∑ [ g cd( i , j ) = 1 ] − i = 1 ∑ n [ g cd( i , i ) = 1 ] = 1 + 2 i = 1 ∑ n φ ( i )
所以做一个线性筛就行了;其实暴力 O ( n 2 log n ) O(n^2\log n) O ( n 2 log n ) 在这个范围同样可以通过。注意特判 n = 1 n=1 n = 1 ,上面的情况都是基于 n ≥ 2 n\ge 2 n ≥ 2 时的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <bits/stdc++.h> using namespace std;const int N = 40010 ;int primes[N], phi[N], cntp;bitset<N> st; void init (int n) { phi[1 ] = 1 ; for (int i = 2 ; i <= n; i++) { if (!st[i]) primes[cntp++] = i, phi[i] = i - 1 ; for (int j = 0 ; primes[j] <= n/i; j++) { st[i * primes[j]] = 1 ; if (i % primes[j]) phi[i * primes[j]] = phi[i] * phi[primes[j]]; else { phi[i * primes[j]] = phi[i] * primes[j]; break ; } } } } int main () { int n, res = 1 ; cin >> n; if (n == 1 ) { cout << 0 << endl; return 0 ; } n--; init (n); for (int i = 1 ; i <= n; i++) res += 2 * phi[i]; cout << res << endl; return 0 ; }
选择美食
餐厅里有 n n n 种美食,每种美食都有一个美味值 a i a_i a i 和价格 c i c_i c i ,小 P 可以选择任意个美食,且每一种美食可以选择多次。
若小 P 选择的美食的编号为 b 1 , b 2 . . . b m b_1\ ,\ b_2\ ...\ b_m b 1 , b 2 ... b m ,则小 P 能得到的满意值则为
∏ i = 1 m a b i \prod\limits_{i=1}^ma_{b_i}
i = 1 ∏ m a b i
现在小 P 想要使他得到的满意值恰好为 d d d ,请你告诉他最少需要花费多少钱。
由于小 P 的口味非常独特,所以他给出的 d d d 一定满足 φ ( d ) ∣ d \varphi\left(d\right)\ |\ d φ ( d ) ∣ d 。
由于小 P 非常不容易满足,故 d d d 将有可能非常大,为了方便表示,小 P 会告诉你三个数 A , B , k A , B , k A , B , k ,那么 d = A k × B d = A^k \times B d = A k × B 。
1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 , 0 ≤ c i ≤ 1 0 9 , 1 ≤ A , B ≤ 1 0 5 , 0 ≤ k ≤ 40 , d ≤ 1 0 201 1\le n\le 10^5, 1\le a_i\le 10^9,0\le c_i\le 10^9,1\le A,B\le 10^5,0\le k\le 40,d\le 10^{201} 1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 , 0 ≤ c i ≤ 1 0 9 , 1 ≤ A , B ≤ 1 0 5 , 0 ≤ k ≤ 40 , d ≤ 1 0 201
本题主要是 φ ( d ) ∣ d \varphi(d)\mid d φ ( d ) ∣ d 引出的性质。首先:
φ ( d ) = d ( 1 − 1 2 ) ( 1 − 1 3 ) ⋯ = d a b φ ( d ) ∣ d ⇔ k d a b = d b = k a \varphi(d)=d(1-\frac{1}{2})(1-\frac{1}{3})\cdots=d\frac{a}{b}\\
\varphi(d)\mid d\Leftrightarrow kd\frac{a}{b}=d\\
b=ka
φ ( d ) = d ( 1 − 2 1 ) ( 1 − 3 1 ) ⋯ = d b a φ ( d ) ∣ d ⇔ k d b a = d b = ka
也就是要求 φ ( d ) = d / k \varphi(d)=d/k φ ( d ) = d / k ,要么 φ ( d ) = d / 2 \varphi(d)=d/2 φ ( d ) = d /2 要么 φ ( d ) = d / 3 \varphi(d)=d/3 φ ( d ) = d /3 ,所以 d d d 只能有 2 , 3 2,3 2 , 3 两个约数。
将每个 a i a_i a i 分解为 2 a 3 b 2^a3^b 2 a 3 b ,设 d = 2 p 3 q d=2^p3^q d = 2 p 3 q ,也就是需要满足 p = ∑ a , q = ∑ b p=\sum a,q=\sum b p = ∑ a , q = ∑ b 的情况下保证花费最小,那么这显然是个背包问题。
在 1 0 9 10^9 1 0 9 范围内,满足 2 a 3 b 2^a3^b 2 a 3 b 形式的数字,如果粗略的算一下就只有 log 2 1 0 9 × log 3 1 0 9 ≈ 563 \log_2 10^9\times \log_310^9\approx 563 log 2 1 0 9 × log 3 1 0 9 ≈ 563 ,这还没容斥就已经这么少了,然后 p , q p,q p , q 的范围分别是 log 2 d , log 3 d \log_2 d,\log_3 d log 2 d , log 3 d ,用 map
去重,复杂度是 O ( log n log 2 a log 2 d ) O(\log n\log^2 a\log^{2}d) O ( log n log 2 a log 2 d ) ,实际上远小于这个数,肯定能过。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <bits/stdc++.h> using namespace std;#define int long long const int N = 100010 ;int f[700 ][450 ], c[N], num[N];bool valid[N];int n, A, B, k;map<int , int > mp; void extract (int & v, int fac, int & cnt) { while (v % fac == 0 ) v /= fac, cnt++; } signed main () { freopen ("food.in" , "r" , stdin); freopen ("food.out" , "w" , stdout); memset (f, 0x3f , sizeof f); f[0 ][0 ] = 0 ; cin >> n; for (int i = 1 , v; i <= n; i++) cin >> num[i]; for (int i = 1 ; i <= n; i++) cin >> c[i]; for (int i = 1 ; i <= n; i++) { int bak = num[i], t1 = 0 , t2 = 0 ; extract (bak, 2 , t1); extract (bak, 3 , t2); if (bak == 1 ) { if (mp.count (num[i])) mp[num[i]] = min (mp[num[i]], c[i]); else mp[num[i]] = c[i]; } } int t1 = 0 , t2 = 0 ; cin >> A >> B >> k; extract (A, 2 , t1); extract (A, 3 , t2); t1 *= k, t2 *= k; extract (B, 2 , t1); extract (B, 3 , t2); for (const auto & entry: mp) { int a = 0 , b = 0 , num = entry.first; extract (num, 2 , a); extract (num, 3 , b); for (int j = a; j <= t1; j++) for (int k = b; k <= t2; k++) f[j][k] = min (f[j][k], f[j-a][k-b] + entry.second); } int res = f[t1][t2]; if (res == 0x3f3f3f3f3f3f3f3f ll) res = -1 ; cout << res << '\n' ; return 0 ; }
[蓝桥杯2018国B] 矩阵求和
给定正整数 n n n ,求:
∑ i = 1 n ∑ j = 1 n ( gcd ( i , j ) ) 2 \sum_{i=1}^n\sum_{j=1}^n \Big(\gcd(i,j)\Big)^2
i = 1 ∑ n j = 1 ∑ n ( g cd( i , j ) ) 2
其中 1 ≤ n ≤ 1 0 7 1\le n\le 10^7 1 ≤ n ≤ 1 0 7 ,答案对 1 0 9 + 7 10^9+7 1 0 9 + 7 取模。
题目链接:P8670 。
由于 gcd \gcd g cd 具有交换律,所以原式具有对称性,所以可以引入限制条件,并减掉重复的项,原式化为:
2 ∑ i = 1 n ∑ j ≤ i ( gcd ( i , j ) ) 2 − ∑ i = 1 n i 2 2\sum_{i=1}^n\sum_{j\le i}\Big(\gcd(i,j)\Big)^2-\sum_{i=1}^ni^2
2 i = 1 ∑ n j ≤ i ∑ ( g cd( i , j ) ) 2 − i = 1 ∑ n i 2
设 S ( n ) = ∑ i = 1 n i 2 S(n)=\sum_{i=1}^n i^2 S ( n ) = ∑ i = 1 n i 2 ,众所周知 S ( n ) = n ( n + 1 ) ( 2 n + 1 ) 6 S(n)=\frac{n(n+1)(2n+1)}{6} S ( n ) = 6 n ( n + 1 ) ( 2 n + 1 ) ,设 d = gcd ( i , j ) d=\gcd(i,j) d = g cd( i , j ) 必然有 d ∣ i , d ∣ j d\mid i,d\mid j d ∣ i , d ∣ j ,所以 gcd ( i / d , j / d ) = 1 \gcd(i/d,j/d)=1 g cd( i / d , j / d ) = 1 ,由于 j ≤ i j\le i j ≤ i 所以 j / d ≤ i / d j/d\le i/d j / d ≤ i / d ,原式可化为:
2 ∑ i = 1 n ∑ d ∣ i d 2 φ ( i d ) − S ( n ) = 2 ∑ i = 1 n ∑ d ∣ i ( i d ) 2 φ ( d ) − S ( n ) 2\sum_{i=1}^n\sum_{d\mid i}d^2\varphi(\frac{i}{d})-S(n)=2\sum_{i=1}^n\sum_{d\mid i}(\frac{i}{d})^2\varphi(d)-S(n)
2 i = 1 ∑ n d ∣ i ∑ d 2 φ ( d i ) − S ( n ) = 2 i = 1 ∑ n d ∣ i ∑ ( d i ) 2 φ ( d ) − S ( n )
注意 d , i / d d,i/d d , i / d 同样具有对称性,然后考虑 φ ( d ) \varphi(d) φ ( d ) 对谁造成了贡献,考虑只有当 i = d , 2 d , … , ⌊ n d ⌋ d i=d,2d,\dots,\lfloor \frac{n}{d}\rfloor d i = d , 2 d , … , ⌊ d n ⌋ d 时才会造成贡献,所以 φ ( d ) \varphi(d) φ ( d ) 的贡献就是 S ( ⌊ n d ⌋ ) S(\lfloor\frac{n}{d}\rfloor) S (⌊ d n ⌋) 。原式等价于:
2 ∑ d = 1 n φ ( d ) S ( ⌊ n d ⌋ ) − S ( n ) 2\sum_{d=1}^n\varphi(d)S(\lfloor\frac{n}{d}\rfloor)-S(n)
2 d = 1 ∑ n φ ( d ) S (⌊ d n ⌋) − S ( n )
线性筛 O ( n ) O(n) O ( n ) 足够通过本题,如果要求更高可以整除分块 + 高级筛法,这里就不拓展了,因为我也不会。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <bits/stdc++.h> using namespace std;const int N = 10000010 , P = 1e9 +7 ;int phi[N], primes[N], cntp;bitset<N> st; void init (int n) { phi[1 ] = 1 ; for (int i = 2 ; i <= n; i++) { if (!st[i]) primes[cntp++] = i, phi[i] = i-1 ; for (int j = 0 ; primes[j] <= n/i; j++) { st[i*primes[j]] = 1 ; if (i % primes[j]) phi[i*primes[j]] = phi[i] * phi[primes[j]]; else { phi[i*primes[j]] = phi[i] * primes[j]; break ; } } } } int S (int n) { return 1ll * n * (n+1 ) % P * (2 * n + 1 ) % P * 166666668ll % P; } int Solve (int n) { int res = 0 ; init (n); for (int i = 1 ; i <= n; i++) res = (res + 1ll * S (n / i) * phi[i]) % P; res = (((2ll * res - S (n)) % P) + P) % P; return res; } int main () { int n; cin >> n; cout << Solve (n) << endl; return 0 ; }
[XJTUPC2024] 筛法
给定正整数 n n n ,求:
∑ i = 1 n ∑ j = 1 n ⌊ n max ( i , j ) ⌋ [ gcd ( i , j ) = 1 ] \sum_{i=1}^n\sum_{j=1}^n \lfloor\frac{n}{\max(i,j)}\rfloor[\gcd(i,j)=1]
i = 1 ∑ n j = 1 ∑ n ⌊ max ( i , j ) n ⌋ [ g cd( i , j ) = 1 ]
其中 1 ≤ n ≤ 1 0 9 1\le n\le 10^9 1 ≤ n ≤ 1 0 9 。
题目链接:P10532 。
首先 i , j i,j i , j 是对称的,所以:
∑ i = 1 n ∑ j = 1 n ⌊ n max ( i , j ) ⌋ [ gcd ( i , j ) = 1 ] = 2 ∑ i = 1 n ∑ j = 1 i ⌊ n i ⌋ [ gcd ( i , j ) = 1 ] − ∑ i = 1 n ⌊ n i ⌋ [ i = 1 ] = 2 ∑ i = 1 n ⌊ n i ⌋ φ ( i ) − n \begin{aligned}
\sum_{i=1}^n\sum_{j=1}^n\lfloor\frac{n}{\max(i,j)}\rfloor[\gcd(i,j)=1]&=2\sum_{i=1}^n\sum_{j=1}^i\lfloor\frac{n}{i}\rfloor[\gcd(i,j)=1]-\sum_{i=1}^n \lfloor\frac{n}{i}\rfloor[i=1]\\
&=2\sum_{i=1}^n\lfloor\frac{n}{i}\rfloor\varphi(i)-n\\
\end{aligned}
i = 1 ∑ n j = 1 ∑ n ⌊ max ( i , j ) n ⌋ [ g cd( i , j ) = 1 ] = 2 i = 1 ∑ n j = 1 ∑ i ⌊ i n ⌋ [ g cd( i , j ) = 1 ] − i = 1 ∑ n ⌊ i n ⌋ [ i = 1 ] = 2 i = 1 ∑ n ⌊ i n ⌋ φ ( i ) − n
观察:⌊ n / i ⌋ \lfloor n/i\rfloor ⌊ n / i ⌋ 是 i i i 的所有倍数中 ≤ n \le n ≤ n 的个数,所以可以枚举 d d d 为其所有合法倍数的因数,使 φ ( d ) \varphi(d) φ ( d ) 贡献到答案,故原式等价于:
2 ∑ i = 1 n ∑ d ∣ i φ ( d ) − n = 2 ∑ i = 1 n i − n = n ( n + 1 ) − n = n 2 \begin{aligned}
2\sum_{i=1}^n\sum_{d\mid i} \varphi(d)-n&=2\sum_{i=1}^n i-n\\
&=n(n+1)-n\\
&=n^2
\end{aligned}
2 i = 1 ∑ n d ∣ i ∑ φ ( d ) − n = 2 i = 1 ∑ n i − n = n ( n + 1 ) − n = n 2
所以代码就不写了。
[SDOI2012] Longge 的问题
给定正整数 n n n ,求:
∑ i = 1 n gcd ( i , n ) \sum_{i=1}^n \gcd(i,n)
i = 1 ∑ n g cd( i , n )
其中 1 ≤ n < 2 32 1\le n\lt 2^{32} 1 ≤ n < 2 32 。
题目链接:P2303 。
还是枚举 d = gcd ( i , n ) d=\gcd(i,n) d = g cd( i , n ) ,则有 d ∣ n d\mid n d ∣ n ,且 d d d 出现的次数为满足 gcd ( i / d , n / d ) = 1 \gcd(i/d,n/d)=1 g cd( i / d , n / d ) = 1 的 i i i 的个数,就是 φ ( n d ) \varphi(\frac{n}{d}) φ ( d n ) ,所以要求的值是:
∑ d ∣ n d φ ( n d ) = ∑ d ∣ n n d φ ( d ) \sum_{d\mid n} d\varphi(\frac{n}{d})=\sum_{d\mid n}\frac{n}{d}\varphi(d)
d ∣ n ∑ d φ ( d n ) = d ∣ n ∑ d n φ ( d )
对 n n n 质因数分解,以质因数分解的形式枚举所有 d ∣ n d\mid n d ∣ n ,这个是 O ( n ) O(\sqrt n) O ( n ) 的,然后对每个 d d d 用解析式求 φ ( d ) \varphi(d) φ ( d ) ,这个大概是 O ( log n ) O(\log n) O ( log n ) 的,所以可以通过本题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <bits/stdc++.h> using namespace std;#define int long long const int K = 1 << 20 ;int n, fac[K], ep[K], dep[K], k, ans;void dfs (int u, int now) { if (u > k) { int phi = now; for (int i = 1 ; i <= k; i++) if (dep[i]) phi -= phi / fac[i]; ans += phi * n / now; return ; } for (dep[u] = 0 ; dep[u] <= ep[u]; dep[u]++, now = now * fac[u]) dfs (u+1 , now); } signed main () { cin >> n; int n_copy = n; for (int i = 2 ; i <= n_copy / i; i++) { if (n_copy % i == 0 ) { int cnt = 0 ; while (n_copy % i == 0 ) n_copy /= i, cnt++; ++k, fac[k] = i, ep[k] = cnt; } } if (n_copy > 1 ) ++k, fac[k] = n_copy, ep[k] = 1 ; dfs (1 , 1 ); cout << ans << endl; return 0 ; }
[湖北省队互测] GCD
给定正整数 n n n ,求 1 ≤ x , y ≤ n 1\le x,y\le n 1 ≤ x , y ≤ n 且 gcd ( x , y ) \gcd(x,y) g cd( x , y ) 为素数的 ( x , y ) (x,y) ( x , y ) 有多少对,其中 ≤ n ≤ 1 0 7 \le n\le 10^7 ≤ n ≤ 1 0 7 。
题目链接:BZOJ2818 。
枚举不超过 n n n 的素数,然后为了书写方便令 N = ⌊ n / p ⌋ N=\lfloor n/p\rfloor N = ⌊ n / p ⌋ :
∑ p ∑ i = 1 n ∑ j = 1 n [ gcd ( i , j ) = p ] = ∑ p ∑ i = 1 n ∑ j = 1 n [ p ∣ i ] [ p ∣ j ] [ gcd ( i p , j p ) = 1 ] = ∑ p ∑ i = 1 ⌊ n p ⌋ ∑ j = 1 ⌊ n p ⌋ [ gcd ( i , j ) = 1 ] = ∑ p ( 2 ∑ i = 1 N ∑ j = 1 i [ gcd ( i , j ) = 1 ] − ∑ i = 1 N [ gcd ( i , i ) = 1 ] ) = ∑ p ( 2 ∑ i = 1 N φ ( i ) − 1 ) \begin{aligned}
\sum_p\sum_{i=1}^n\sum_{j=1}^n[\gcd(i,j)=p]&=\sum_{p}\sum_{i=1}^n\sum_{j=1}^n[p\mid i][p\mid j][\gcd(\frac{i}{p},\frac{j}{p})=1]\\
&=\sum_p\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{p}\rfloor}[\gcd(i,j)=1]\\
&=\sum_p\left(2\sum_{i=1}^N\sum_{j=1}^i[\gcd(i,j)=1]-\sum_{i=1}^N[\gcd(i,i)=1]\right)\\
&=\sum_p\left(2\sum_{i=1}^N\varphi(i)-1\right)\\
\end{aligned}
p ∑ i = 1 ∑ n j = 1 ∑ n [ g cd( i , j ) = p ] = p ∑ i = 1 ∑ n j = 1 ∑ n [ p ∣ i ] [ p ∣ j ] [ g cd( p i , p j ) = 1 ] = p ∑ i = 1 ∑ ⌊ p n ⌋ j = 1 ∑ ⌊ p n ⌋ [ g cd( i , j ) = 1 ] = p ∑ ( 2 i = 1 ∑ N j = 1 ∑ i [ g cd( i , j ) = 1 ] − i = 1 ∑ N [ g cd( i , i ) = 1 ] ) = p ∑ ( 2 i = 1 ∑ N φ ( i ) − 1 )
线性筛 O ( n ) O(n) O ( n ) 预处理 φ ( i ) \varphi(i) φ ( i ) 的前缀和与不超过 n n n 的素数,所以总复杂度为 O ( n ) O(n) O ( n ) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <bits/stdc++.h> using namespace std;const int N = 10000010 ;int n, primes[N], cntp;long long ans, phi[N];bitset<N> st; void init (int n) { phi[1 ] = 1 ; for (int i = 2 ; i <= n; i++) { if (!st[i]) primes[cntp++] = i, phi[i] = i-1 ; for (int j = 0 ; primes[j] <= n/i; j++) { st[i * primes[j]] = 1 ; if (i % primes[j]) phi[i * primes[j]] = phi[i] * phi[primes[j]]; else { phi[i * primes[j]] = phi[i] * primes[j]; break ; } } } for (int i = 1 ; i <= n; i++) phi[i] += phi[i-1 ]; } int main () { cin >> n; init (n); for (int i = 0 ; i < cntp; i++) ans += 2ll * phi[n / primes[i]] - 1 ; cout << ans << endl; return 0 ; }