题 意 \large题意 题意
题目链接
给 定 N , M , 求 1 ≤ x ≤ N , 1 ≤ y ≤ M 且 g c d ( x , y ) 为 质 数 的 ( x , y ) 有 多 少 对 给定N, M,求1 \leq x \leq N, 1 \leq y \leq M且 gcd(x, y)为质数的(x, y)有多少对 给定N,M,求1≤x≤N,1≤y≤M且gcd(x,y)为质数的(x,y)有多少对
用 式 子 表 达 出 来 为 用式子表达出来为 用式子表达出来为
∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] , k ∈ P r i m e \sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i, j) = k], k \in Prime i=1∑nj=1∑m[gcd(i,j)=k],k∈Prime
题 解 \large题解 题解
为 了 讨 论 方 便 , 我 们 假 设 n < m 为了讨论方便,我们假设n < m 为了讨论方便,我们假设n<m
原 式 = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] , k ∈ p r i m e = ∑ k = 1 n ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] , k ∈ p r i m e , 后 面 省 略 这 句 话 = ∑ k = 1 n ∑ i = 1 n / k ∑ j = 1 m / k [ g c d ( i , j ) = 1 ] = ∑ k = 1 n ∑ i = 1 n / k ∑ j = 1 m / k ∑ d ∣ g c d ( i , j ) n / k μ ( d ) = ∑ k = 1 n ∑ d = 1 n / k μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ \begin{aligned} \qquad\qquad\qquad 原式 &=\sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i, j) = k], k \in prime \\ &= \sum_{k=1}^{n} \sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i, j) = k], k \in prime, 后面省略这句话 \\ &= \sum_{k=1}^{n} \sum_{i=1}^{n/k} \sum_{j=1}^{m/k} [gcd(i, j) = 1] \\ &= \sum_{k=1}^{n} \sum_{i=1}^{n/k} \sum_{j=1}^{m/k} \sum_{d|gcd(i, j)}^{n/k} \mu(d) \\ &= \sum_{k=1}^{n} \sum_{d=1}^{n/k} \mu(d) \lfloor \frac{n}{kd}\rfloor \lfloor \frac{m}{kd}\rfloor \end{aligned} 原式=i=1∑nj=1∑m[gcd(i,j)=k],k∈prime=k=1∑ni=1∑nj=1∑m[gcd(i,j)=k],k∈prime,后面省略这句话=k=1∑ni=1∑n/kj=1∑m/k[gcd(i,j)=1]=k=1∑ni=1∑n/kj=1∑m/kd∣gcd(i,j)∑n/kμ(d)=k=1∑nd=1∑n/kμ(d)⌊kdn⌋⌊kdm⌋
在 这 里 我 们 枚 举 素 数 k , 可 以 得 到 答 案 , 但 是 实 际 上 会 T L E , 我 们 考 虑 如 何 进 一 步 优 化 在这里我们枚举素数k,可以得到答案,但是实际上会TLE,我们考虑如何进一步优化 在这里我们枚举素数k,可以得到答案,但是实际上会TLE,我们考虑如何进一步优化
我 们 设 T = k d , 则 d = T k 那 么 有 我们设T=kd,则d=\frac{T}{k} 那么有 我们设T=kd,则d=kT那么有
原 式 = ∑ k = 1 n ∑ d = 1 n / k μ ( d ) ⌊ n k d ⌋ ⌊ m k d ⌋ = ∑ k = 1 n ∑ d = 1 n / k μ ( d ) ⌊ n T ⌋ ⌊ m T ⌋ \begin{aligned} \qquad\qquad\qquad 原式 &=\sum_{k=1}^{n} \sum_{d=1}^{n/k} \mu(d) \lfloor \frac{n}{kd}\rfloor \lfloor \frac{m}{kd}\rfloor \\ &= \sum_{k=1}^{n} \sum_{d=1}^{n/k} \mu(d) \lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor \\ \end{aligned} 原式=k=1∑nd=1∑n/kμ(d)⌊kdn⌋⌊kdm⌋=k=1∑nd=1∑n/kμ(d)⌊Tn⌋⌊Tm⌋
这 个 式 子 , 现 在 是 先 枚 举 素 数 k , 然 后 枚 举 d , 我 们 考 虑 直 接 枚 举 T 这个式子,现在是先枚举素数k,然后枚举d,我们考虑直接枚举T 这个式子,现在是先枚举素数k,然后枚举d,我们考虑直接枚举T
原 式 = ∑ k = 1 n ∑ d = 1 n / k μ ( d ) ⌊ n T ⌋ ⌊ m T ⌋ = ∑ T = 1 n ⌊ n T ⌋ ⌊ m T ⌋ ∑ k ∈ p r i m e , k ∣ T μ ( T k ) = ∑ T = 1 n ⌊ n T ⌋ ⌊ m T ⌋ ∑ k ∈ p r i m e , k ∣ T μ ( T k ) \begin{aligned} \qquad\qquad\qquad 原式 &=\sum_{k=1}^{n} \sum_{d=1}^{n/k} \mu(d) \lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor \\ &= \sum_{T=1}^{n} \lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor \sum_{k \in prime, k|T} \mu (\frac{T}{k}) \\ &= \sum_{T=1}^{n} \lfloor \frac{n}{T}\rfloor \lfloor \frac{m}{T}\rfloor \boxed{\sum_{k \in prime, k|T} \mu (\frac{T}{k})} \\ \end{aligned} 原式=k=1∑nd=1∑n/kμ(d)⌊Tn⌋⌊Tm⌋=T=1∑n⌊Tn⌋⌊Tm⌋k∈prime,k∣T∑μ(kT)=T=1∑n⌊Tn⌋⌊Tm⌋k∈prime,k∣T∑μ(kT)
注 意 到 , 最 后 的 东 西 , 是 可 以 预 处 理 的 注意到,最后的东西,是可以预处理的 注意到,最后的东西,是可以预处理的
考 虑 每 一 个 素 数 k , 对 于 k 的 倍 数 T , 把 它 的 值 加 上 μ ( T k ) 考虑每一个素数k,对于k的倍数T,把它的值加上\mu (\frac{T}{k}) 考虑每一个素数k,对于k的倍数T,把它的值加上μ(kT)
预 处 理 代 码 如 下 \large预处理代码如下 预处理代码如下
void sieve() {
mu[1]=1;
for (int i=2;i<=10000000;i++) {
if (!flag[i]) prime[++cnt]=i,mu[i]=-1;
for (int j=1;j<=cnt&&i*prime[j]<=10000000;j++) {
flag[i*prime[j]]=1;
if (i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
for (int i=1;i<=cnt;i++)
for (int j=1;prime[i]*j<=10000000;j++)
f[j*prime[i]]+=mu[j];
for (int i=1;i<=10000000;i++)
sum[i]=sum[i-1]+f[i];
}
我 们 推 式 子 比 较 重 要 的 一 步 是 用 了 我们推式子比较重要的一步是用了 我们推式子比较重要的一步是用了
∑ d ∣ g c d ( i , j ) μ ( d ) = [ g c d ( i , j ) = 1 ] \sum_{d|gcd(i, j)} \mu(d) = [gcd(i, j) = 1] d∣gcd(i,j)∑μ(d)=[gcd(i,j)=1]
这 个 在 许 多 题 目 中 都 会 用 到 , 是 一 个 比 较 套 路 的 用 法 这个在许多题目中都会用到,是一个比较套路的用法 这个在许多题目中都会用到,是一个比较套路的用法
同 样 的 , 我 们 可 以 使 用 莫 比 乌 斯 反 演 来 推 式 子 , 得 到 同 样 的 结 果 同样的,我们可以使用莫比乌斯反演来推式子,得到同样的结果 同样的,我们可以使用莫比乌斯反演来推式子,得到同样的结果
我 们 设 f ( d ) = g c d ( i , j ) = d 的 个 数 , F ( n ) 为 g c d ( i , j ) 为 d 的 倍 数 的 个 数 , 我 们 有 我们设f(d) = gcd(i, j) = d的个数, F(n)为gcd(i, j)为d的倍数的个数,我们有 我们设f(d)=gcd(i,j)=d的个数,F(n)为gcd(i,j)为d的倍数的个数,我们有
f ( d ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] f(d) = \sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i, j) = d] f(d)=i=1∑nj=1∑m[gcd(i,j)=d]
F ( n ) = ∑ i = 1 n / i f ( d ⋅ i ) = ⌊ n d ⌋ ⌊ m d ⌋ F(n) = \sum_{i=1}^{n/i}f(d\cdot i) = \lfloor \frac{n}{d}\rfloor \lfloor \frac{m}{d}\rfloor F(n)=i=1∑n/if(d⋅i)=⌊dn⌋⌊dm⌋
得 到 得到 得到
f ( d ) = ∑ i = 1 n / d μ ( i ) F ( d ⋅ i ) f(d) =\sum_{i=1}^{n/d} \mu(i) F(d \cdot i) f(d)=i=1∑n/dμ(i)F(d⋅i)
接 着 , 接着, 接着,
原 式 = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] , k ∈ p r i m e = ∑ k , k ∈ p r i m e n f ( k ) = ∑ k , k ∈ p r i m e n ∑ i = 1 n / k μ ( i ) ⌊ n d i ⌋ ⌊ m d i ⌋ \begin{aligned} \qquad\qquad\qquad 原式 &=\sum_{i=1}^{n} \sum_{j=1}^{m} [gcd(i, j) = k], k \in prime \\ &= \sum_{k, k \in prime}^{n} f(k) \\ &= \sum_{k, k \in prime}^{n} \sum_{i=1}^{n/k} \mu(i) \lfloor \frac{n}{di}\rfloor \lfloor \frac{m}{di}\rfloor\\ \end{aligned} 原式=i=1∑nj=1∑m[gcd(i,j)=k],k∈prime=k,k∈prime∑nf(k)=k,k∈prime∑ni=1∑n/kμ(i)⌊din⌋⌊dim⌋
i 替 换 为 字 母 k 后 , 和 上 面 是 相 同 的 结 果 i替换为字母k后,和上面是相同的结果 i替换为字母k后,和上面是相同的结果
完 整 A C 代 码 \large完整AC代码 完整AC代码
#include
using namespace std;
typedef long long LL;
const int N = 10000000;
LL mu[N + 10];
LL flag[N + 10];
LL prime[N + 10];
LL cnt;
LL f[N + 10];
LL sum[N + 10];
void init() {
mu[1] = 1;
for (int i = 2; i <= N; i++) {
if (!flag[i]) prime[++cnt] = i, mu[i] = -1;
for (int j = 1; j <= cnt && i * prime[j] <= N; j++) {
flag[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
mu[i * prime[j]] = -mu[i];
}
}
for (int i = 1; i <= cnt; i++) {
for (int j = 1; prime[i] * j <= N; j++) {
f[j * prime[i]] += mu[j];
}
}
for (int i = 1; i <= N; i++) sum[i] = sum[i - 1] + f[i];
}
LL solve(int n, int m) {
LL ans = 0;
for (int l = 1, r; l <= n; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += (LL)(sum[r] - sum[l-1]) * (LL)(n / l) * (LL)(m / l);
}
return ans;
}
int main() {
init();
int n, m, T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
if (n > m) swap(n, m);
printf("%lld\n", solve(n, m));
}
return 0;
}