题面:bzoj4652
题意:对于 1 ≤ x ≤ n 1 \le x \le n 1≤x≤n, 1 ≤ y ≤ m 1 \le y \le m 1≤y≤m,有多少个在 k k k进制下数值互不相等的纯循环小数 x y \frac x y yx。 1 ≤ n , m ≤ 1 0 9 1 \le n, m \le 10^9 1≤n,m≤109, 2 ≤ k ≤ 2000 2 \le k \le 2000 2≤k≤2000
题解:首先考虑10进制下的纯循环小数,一定可以表示成 a 1 0 k − 1 \frac a {10 ^k - 1} 10k−1a的形式(不一定是最减分数)
猜想 k k k进制下可以表示成 a k b − 1 \frac a {k^b - 1} kb−1a,所以 y ∣ ( k b − 1 ) y \mid (k^b - 1) y∣(kb−1)
即 k b − 1 ≡ 0 ( m o d y ) → k b ≡ 1 ( m o d y ) k^b-1 \equiv 0 \pmod y \to k^b \equiv 1 \pmod y kb−1≡0(mody)→kb≡1(mody)
所以 g c d ( k , y ) = 1 gcd (k, y) = 1 gcd(k,y)=1。又因为是最简分数(要求数值互不相等),所以 g c d ( x , y ) = 1 gcd (x, y) = 1 gcd(x,y)=1
这一段也可以用纯循环小数定义证明: x k b ≡ x ( m o d y ) xk^b \equiv x \pmod y xkb≡x(mody)
所以问题变成求: ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] [ g c d ( j , k ) ] = 1 \sum _{i=1} ^n \sum _{j=1} ^m [gcd (i, j) = 1] [gcd (j, k)] = 1 ∑i=1n∑j=1m[gcd(i,j)=1][gcd(j,k)]=1
∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] [ g c d ( j , k ) = 1 ] = ∑ j = 1 m [ g c d ( j , k ) = 1 ] ∑ i = 1 n [ g c d ( i , j ) = 1 ] = ∑ j = 1 m [ g c d ( j , k ) = 1 ] ∑ i = 1 n ∑ d ∣ i , d ∣ j μ ( d ) = ∑ d = 1 n μ ( d ) ∑ d ∣ i n ∑ d ∣ j m [ g c d ( j , k ) = 1 ] = ∑ d = 1 n [ g c d ( d , k ) = 1 ] μ ( d ) ∑ i = 1 n d ∑ j = 1 m d [ g c d ( j , k ) = 1 ] = ∑ d = 1 n [ g c d ( d , k ) = 1 ] μ ( d ) ⌊ n d ⌋ ∑ j = 1 m d [ g c d ( j , k ) = 1 ] \begin {aligned} & \sum _{i=1} ^n \sum _{j=1} ^m [gcd (i, j) = 1] [gcd (j, k) = 1] \\ = & \sum _{j=1} ^m [gcd (j, k) = 1] \sum _{i=1} ^n [gcd (i, j) = 1] \\ = & \sum _{j=1} ^m [gcd (j, k) = 1] \sum _{i=1} ^n \sum _{d \mid i, d \mid j} \mu (d) \\ = & \sum _{d=1} ^n \mu (d) \sum _{d \mid i} ^n \sum _{d \mid j} ^m [gcd (j, k) = 1] \\ = & \sum _{d = 1} ^n [gcd (d, k) = 1] \mu (d) \sum _{i = 1} ^{\frac n d} \sum _{j=1} ^{\frac m d} [gcd (j, k) = 1] \\ = & \sum _{d = 1} ^n [gcd (d, k) = 1] \mu (d) \lfloor \frac n d \rfloor \sum _{j=1} ^{\frac m d} [gcd (j, k) = 1] \end {aligned} =====i=1∑nj=1∑m[gcd(i,j)=1][gcd(j,k)=1]j=1∑m[gcd(j,k)=1]i=1∑n[gcd(i,j)=1]j=1∑m[gcd(j,k)=1]i=1∑nd∣i,d∣j∑μ(d)d=1∑nμ(d)d∣i∑nd∣j∑m[gcd(j,k)=1]d=1∑n[gcd(d,k)=1]μ(d)i=1∑dnj=1∑dm[gcd(j,k)=1]d=1∑n[gcd(d,k)=1]μ(d)⌊dn⌋j=1∑dm[gcd(j,k)=1]
相当于需要求两个前缀和:
f ( x ) = ∑ i = 1 x [ g c d ( i , k ) ] = 1 f(x) = \sum _{i=1} ^x [gcd (i, k)] = 1 f(x)=∑i=1x[gcd(i,k)]=1
S ( x , k ) = ∑ i = 1 x μ ( i ) [ g c d ( i , k ) = 1 ] S(x, k) = \sum _{i=1} ^x \mu (i) [gcd (i, k) = 1] S(x,k)=∑i=1xμ(i)[gcd(i,k)=1]
先看 f ( x ) f(x) f(x):若 g c d ( a , k ) = 1 gcd (a, k) = 1 gcd(a,k)=1,则 g c d ( a + n k , k ) = 1 gcd (a + nk, k) = 1 gcd(a+nk,k)=1。最后一段可能不满足,单独考虑。
f ( x ) = ⌊ x k ⌋ f ( k ) + f ( x % k ) f(x) = \lfloor \frac x k \rfloor f (k) + f (x \% k) f(x)=⌊kx⌋f(k)+f(x%k)
k ≤ 2000 k \le 2000 k≤2000,直接预处理计算。
S ( x , k ) = ∑ i = 1 x μ ( i ) [ g c d ( i , k ) = 1 ] = ∑ i = 1 x μ ( i ) ∑ d ∣ i , d ∣ k μ ( d ) = ∑ d ∣ k μ ( d ) ∑ d ∣ i μ ( i ) = ∑ d ∣ k μ ( d ) ∑ i = 1 x d μ ( i d ) \begin {aligned} S (x, k) & = \sum _{i=1} ^x \mu (i) [gcd (i, k) = 1] \\ & = \sum _{i=1} ^x \mu (i) \sum _{d \mid i, d \mid k} \mu (d) \\ &= \sum _{d \mid k} \mu (d) \sum _{d \mid i} \mu (i) \\ &= \sum _{d \mid k} \mu (d) \sum _{i=1} ^{\frac x d} \mu (id) \end {aligned} S(x,k)=i=1∑xμ(i)[gcd(i,k)=1]=i=1∑xμ(i)d∣i,d∣k∑μ(d)=d∣k∑μ(d)d∣i∑μ(i)=d∣k∑μ(d)i=1∑dxμ(id)
若 g c d ( i , d ) ̸ = 1 gcd (i, d) \not= 1 gcd(i,d)̸=1,则 μ ( i d ) = 0 \mu (id) = 0 μ(id)=0
S ( x , k ) = ∑ d ∣ k μ ( d ) ∑ i = 1 , g c d ( i , d ) = 1 x d μ ( i ) μ ( d ) = ∑ d ∣ k μ ( d ) 2 ∑ i = 1 , g c d ( i , d ) = 1 x d μ ( i ) = ∑ d ∣ k μ ( d ) 2 ∑ i = 1 x d μ ( i ) [ g c d ( i , d ) = 1 ] = ∑ d ∣ k μ ( d ) 2 S ( ⌊ x d ⌋ , d ) \begin {aligned} S(x, k) &= \sum _{d \mid k} \mu (d) \sum _{i=1, gcd (i, d) = 1} ^{\frac x d} \mu (i) \mu (d) \\ &= \sum _{d \mid k} \mu (d) ^2 \sum _{i=1, gcd (i, d) = 1} ^{\frac x d} \mu (i) \\ &= \sum _{d \mid k} \mu (d) ^2 \sum _{i=1} ^{\frac x d} \mu (i) [gcd (i, d) = 1] \\ &= \sum _{d \mid k} \mu (d) ^2 S (\lfloor \frac x d \rfloor, d) \end {aligned} S(x,k)=d∣k∑μ(d)i=1,gcd(i,d)=1∑dxμ(i)μ(d)=d∣k∑μ(d)2i=1,gcd(i,d)=1∑dxμ(i)=d∣k∑μ(d)2i=1∑dxμ(i)[gcd(i,d)=1]=d∣k∑μ(d)2S(⌊dx⌋,d)
若 k ≠ 1 k \neq 1 k̸=1,递归计算。
若 k = 1 k = 1 k=1, S ( x , k ) = ∑ i = 1 x μ ( i ) S(x, k) = \sum _{i=1} ^x \mu (i) S(x,k)=∑i=1xμ(i),杜教筛:
S ( n ) = ∑ i = 1 n μ ( i ) S(n) = \sum _{i=1} ^n \mu (i) S(n)=∑i=1nμ(i)
g ( 1 ) S ( n ) = ∑ i = 1 n ( g ∗ f ) ( i ) − ∑ i = 2 n g ( i ) S ( n i ) g(1)S(n) = \sum _{i=1} ^n (g * f) (i) - \sum _{i=2} ^n g(i) S(\frac n i) g(1)S(n)=∑i=1n(g∗f)(i)−∑i=2ng(i)S(in)
取 g ( x ) = 1 g(x) = 1 g(x)=1
S ( n ) = 1 − ∑ i = 2 n S ( n i ) S(n) = 1 - \sum _{i=2} ^n S (\frac n i) S(n)=1−∑i=2nS(in)
a n s = ∑ d = 1 n [ g c d ( d , k ) = 1 ] μ ( d ) ⌊ n d ⌋ ∑ j = 1 m d [ g c d ( j , k ) = 1 ] ans = \sum _{d = 1} ^n [gcd (d, k) = 1] \mu (d) \lfloor \frac n d \rfloor \sum _{j=1} ^{\frac m d} [gcd (j, k) = 1] ans=∑d=1n[gcd(d,k)=1]μ(d)⌊dn⌋∑j=1dm[gcd(j,k)=1]
前半部分记忆化,后半部分预处理 O ( 1 ) O(1) O(1)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll ;
typedef pair<int, int> P ;
const int maxn = 1e7 + 10 ;
int n, m, k ;
int prime[maxn], tot ;
int mu[maxn], summu[maxn], f[5010] ;
bool vis[maxn] ;
map<P, ll> ss ;
int gcd (int a, int b) {
return b ? gcd (b, a % b) : a ;
}
void init() {
for (int i = 1; i <= k; i ++)
if (gcd (i, k) == 1) f[i] = 1 ;
for (int i = 1; i <= k; i ++) f[i] += f[i - 1] ;
mu[1] = 1 ;
for (int i = 2; i < maxn; i ++) {
if (!vis[i]) prime[++ tot] = i, mu[i] = -1 ;
for (int j = 1; j <= tot && i * prime[j] < maxn; j ++) {
vis[i * prime[j]] = 1 ;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0; break ;
}
mu[i * prime[j]] = -mu[i] ;
}
}
for (int i = 1; i < maxn; i ++) summu[i] = summu[i - 1] + mu[i] ;
}
ll SS (int x, int k) {
if ((!x) || (k == 1 && x < maxn)) return summu[x] ;
if (ss[P (x, k)]) return ss[P (x, k)] ;
ll res = 0 ;
if (k == 1) {
res = 1 ;
for (int i = 2, j; i <= x; i = j + 1) {
j = x / (x / i) ;
res -= (j - i + 1) * SS (x / i, 1) ;
}
} else {
for (int i = 1; i * i <= k; i ++) {
if (k % i == 0) {
if (mu[i]) res += SS (x / i, i) ;
if (i * i != k && mu[k / i]) res += SS (x / (k / i), k / i) ;
}
}
}
return ss[P (x, k)] = res ;
}
ll SF (int x) {
return 1ll * (x / k) * f[k] + f[x % k] ;
}
int main() {
cin >> n >> m >> k ;
init () ;
ll ans = 0, pre = 0, cur ;
for (int i = 1, j; i <= min (n, m); i = j + 1) {
j = min (n / (n / i), m / (m / i)) ;
cur = SS (j, k) ;
ans += 1ll * (cur - pre) * (n / i) * SF (m / i) ;
pre = cur ;
}
cout << ans << endl ;
return 0 ;
}