2024.7 做题记录
放暑假了 > <
P3935 Calculating
设 \(g(n) = \displaystyle \sum_{i=1}^n d(i)\),答案即为 \(g(r) - g(l - 1)\)。
\[g(n) = \displaystyle \sum_{i = 1}^n \sum_{j = 1}^i[j | i]
\]
考虑改变贡献方式,统计每个数会贡献到哪些 \(i \in [1, n]\)。
\[g(n) = \sum_{i = 1}^n\lfloor \dfrac{n}{i} \rfloor
\]
整除分块。
// 如果命运对你缄默, 那就活给他看。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
// #define int LL
LL l, r;
const int p = 998244353;
inline int g(LL n) {
LL ans = 0;
for(LL l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans = ans + (r - l + 1) * (n / l) % p;
ans = ans % p;
}
return ans;
}
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> l >> r;
cout << (g(r) - g(l - 1) + p) % p << '\n';
return 0;
}
P2261 [CQOI2007] 余数求和
\[\begin{aligned}
\sum_{i = 1}^n k \bmod i =&\sum_{i = 1}^nk-i\lfloor \dfrac{n}{i} \rfloor\\
&=nk - \sum^{n}_{i = 1} i\lfloor \dfrac{n}{i} \rfloor \\
\end{aligned}
\]
整除分块。
// 如果命运对你缄默, 那就活给他看。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
// #define int LL
int n, k;
inline LL G(int n, int k) {
LL ans = 0;
for(int l = 1, r; l <= min(n, k); l = r + 1) {
r = min(n, k / (k / l));
ans += 1LL * (k / l) * (l + r) * (r - l + 1) / 2;
}
ans = -ans + 1LL * n * k;
return ans;
}
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> k;
cout << G(n, k) << '\n';
return 0;
}
P1829 [国家集训队] Crash的数字表格
首先有
\[h(n, m) = \sum_{i = 1}^n \sum_{j = 1}^m \text{lcm}(i, j) = \sum_{i = 1}^n \sum_{j = 1}^m \dfrac{ij}{\gcd(i, j)} \\
\]
然后考虑枚举 \(d = \gcd(i, j)\)
\[\sum_{i = 1}^n \sum_{j = 1}^m \sum_{d|i, d|j, \gcd(\frac{i}{d}, \frac{j}{d}) = 1}\dfrac{ij}{d}
\]
改为枚举 \(\frac{i}{d}, \frac{j}{d}\),这样每一对都唯一对应到另一对
\[\begin{aligned}
\sum_{d = 1}^n \sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor} \sum_{j = 1}^{\lfloor \frac{m}{d}\rfloor}ijd[\gcd(i,j)=1]
&=\sum_{d = 1}^n d\sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor} \sum_{j = 1}^{\lfloor \frac{m}{d}\rfloor}ij[\gcd(i,j)=1]\\
\end{aligned}\]
后面的部分是一个矩形内的互质对之积,考虑设 \(f(n, m) =\displaystyle\sum_{i = 1}^{n} \sum_{j = 1}^{m}ij[\gcd(i,j)=1]\)
把 \([\gcd(i, j) = 1]\) 替换成 \(\varepsilon\),再莫反一下
\[\displaystyle\sum_{i = 1}^{n} \sum_{j = 1}^{m}\sum_{d | \gcd(i, j)}\mu(d) ij \\
\]
把这个枚举约数往外面拿
\[\displaystyle \sum_{d = 1} \sum_{i = 1}^{n} \sum_{j = 1}^{m}\mu(d) ij[d | i][d | j]
\]
同样是枚举消掉 \(d\) 后的对
\[\displaystyle \sum_{d = 1} \mu(d) d^2 \sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor} \sum_{j = 1}^{\lfloor \frac{m}{d}\rfloor}ij
\]
后面这个东西可以拿出来做,有
\[g(n, m) = \sum_{i = 1}^n\sum_{j = 1}^mij \\
=\dfrac{(1 + n)n}{2} \times \dfrac{(1 + m)m}{2}\]
于是有
\[f(n, m) = \displaystyle \sum_{d = 1} \mu(d) d^2 g(\lfloor \frac{n}{d}\rfloor, \lfloor \frac{m}{d}\rfloor)
\]
\[h(n, m) = \sum_{d = 1}^n d\ f(\lfloor \frac{n}{d}\rfloor, \lfloor \frac{m}{d}\rfloor)
\]
分别整除分块即可,复杂度 \(O(n)\)。
// 如果命运对你缄默, 那就活给他看。
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
// #define int LL
const int maxn = 1e7 + 10;
const int p = 20101009;
int mu[maxn], pr[maxn], tot = 0, s[maxn];
inline void Euler() {
mu[1] = 1;
bitset <maxn> st;
for(int i = 2; i < maxn; ++ i) {
if(!st[i]) pr[++ tot] = i, mu[i] = -1;
for(int j = 1; pr[j] * i < maxn && j <= tot; ++ j) {
st[pr[j] * i] = 1;
if(i % pr[j] == 0) {
mu[i * pr[j]] = 0;
break;
}
mu[pr[j] * i] = -mu[i];
}
}
for(int i = 1; i < maxn; ++ i) {
s[i] = 1LL * i * i % p * (mu[i] + p) % p;
s[i] = (s[i] + s[i - 1]) % p;
}
}
int n, m;
inline int g(int n, int m) {
int p = (1LL * n + 1LL) * n / 2 % ::p,
q = (1LL * m + 1LL) * m / 2 % ::p;
return 1LL * p * q % ::p;
}
inline int f(int n, int m) {
LL ans = 0;
for(int l = 1, r; l <= min(n, m); l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += 1LL * (s[r] - s[l - 1] + p) % p * g(n / l, m / l) % p;
ans %= p;
}
return ans;
}
inline int h(int n, int m) {
int ans = 0;
for(int l = 1, r; l <= min(n, m); l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans += 1LL * (l + r) * (r - l + 1) / 2 % p * f(n / l, m / l) % p;
ans %= p;
}
return ans;
}
signed main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
Euler();
cin >> n >> m;
cout << h(n, m) << '\n';
return 0;
}
BZOJ2693 jzptab
多组询问。