洛谷 P1829 [国家集训队]Crash的数字表格 / JZPTAB
题意
求
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\text{lcm}(i,j)(\bmod 20101009)
\]
思路
容易想到原式等价于
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\frac{ij}{\gcd(i,j)}
\]
枚举 \(i,j\) 的最大公约数 \(d\),显然 \(\gcd(\frac id,\frac jd)=1\),即 \(\frac id\) 和 \(\frac jd\) 互质
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^m\sum\limits_d[d|i][d|j][\gcd(\frac id,\frac jd)=1]\frac{ij}d
\]
变换求和顺序,改为先枚举 \(d\),则可以得到:
\[\sum\limits_{d=1}\sum\limits_{i=1}^{n}[d|i]\sum\limits_{j=1}^{m}[d|j][\gcd(\frac id,\frac jd)=1]\frac{ij}{d}
\]
把后面的 \(d\) 提取出来,对应的两个 \(\sum\) 改为枚举 \(\frac id,\frac jd\),进一步化简可以得到:
\[\begin{aligned}&\sum\limits_{d=1}\sum\limits_{i=1}^{n}[d|i]\sum\limits_{j=1}^{m}[d|j][\gcd(\frac id,\frac jd)=1]\frac{ij}{d}\\=&\sum\limits_{d=1}\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1]\frac{id\times jd}{d}\\=&\sum\limits_{d=1}\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1]ijd\\=&\sum\limits_{d=1}^{n}d\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1]ij\end{aligned}
\]
先搁置这个式子,考虑后半部分。
记 \(sum(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[\gcd(i,j)=1]ij\),对其进行化简,用 \(\varepsilon(\gcd(i,j))\)(即\(\sum\limits_{d|gcd(i,j)}\mu(d)\)) 替换\([\gcd(i,j)=1]\),得到
\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sum\limits_{d|\gcd(i,j)}\mu(d)ij
\]
转化为首先枚举约数
\[\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{n}[d|i]\sum\limits_{j=1}^{m}[d|j]ij
\]
像上面一样,后面的式子中考虑把 \(d\) 提取出来,直接枚举满足条件的数,得到
\[\begin{aligned}&\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{n}[d|i]\sum\limits_{j=1}^{m}[d|j]ij\\&=\sum\limits_{d=1}^{\min(n,m)}\mu(d)\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}id\times jd\\&=\sum\limits_{d=1}^{\min(n,m)}\mu(d)\times d^2\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}ij\end{aligned}
\]
前半段可以处理前缀和,后半段可以 \(O(1)\) 求,因为设
\[Q(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}ij=\frac{n\times(n+1)}{2}\times\frac{m\times(m+1)}{2}
\]
的话,这个函数显然可以\(O(1)\)求解
到现在
\[sum(n,m)=\sum\limits_{d=1}^{\min(n,m)}\mu(d)\times d^2\times Q(\lfloor\frac nd \rfloor,\lfloor\frac md\rfloor)
\]
可以用数论分块求解
回带到原式中
\[\sum\limits_{d=1}^{\min(n, m)}d\times sum(\lfloor\frac nd \rfloor,\lfloor\frac md\rfloor)
\]
这样的话,又可以数论分块求解了,然后就做完啦
代码
/*
Author:loceaner
*/
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int A = 1e7 + 11;
const int B = 1e6 + 11;
const int mod = 20101009;
const int inf = 0x3f3f3f3f;
inline int read() {
char c = getchar(); int x = 0, f = 1;
for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
return x * f;
}
bool vis[A];
int n, m, mu[A], p[B], sum[A], cnt;
void getmu() {
mu[1] = 1;
int k = min(n, m);
for (int i = 2; i <= k; i++) {
if (!vis[i]) p[++cnt] = i, mu[i] = -1;
for (int j = 1; j <= cnt && i * p[j] <= k; ++j) {
vis[i * p[j]] = 1;
if (i % p[j] == 0) break;
mu[i * p[j]] = -mu[i];
}
}
for (int i = 1; i <= k; i++) sum[i] = (sum[i - 1] + i * i % mod * mu[i]) % mod;
}
int Sum(int x, int y) {
return (x * (x + 1) / 2 % mod) * (y * (y + 1) / 2 % mod) % mod;
}
int solve2(int x, int y) {
int res = 0;
for (int i = 1, j; i <= min(x, y); i = j + 1) {
j = min(x / (x / i), y / (y / i));
res = (res + 1LL * (sum[j] - sum[i - 1] + mod) * Sum(x / i, y / i) % mod) % mod;
}
return res;
}
int solve(int x, int y) {
int res = 0;
for (int i = 1, j; i <= min(x, y); i = j + 1) {
j = min(x / (x / i), y / (y / i));
res = (res + 1LL * (j - i + 1) * (i + j) / 2 % mod * solve2(x / i, y / i) % mod) % mod;
}
return res;
}
signed main() {
n = read(), m = read();
getmu();
cout << solve(n, m) << '\n';
}
转载不必联系作者,但请声明出处