题解:P15765 [JAG 2025 Summer Camp #1] Sum of Floor(N/ij)
update:时间复杂度还是有锅,麻烦管理了……
update:被指出时间复杂度分析错误,修改后重交。
这道题显然可以整除分块套整除分块,但是时间复杂度 好像有人过了?
所以我们考虑将式子变形。对于原式,记
前面的一部分显然,
我们用线性筛预处理
首先,预处理是
但是由于使用了记忆化严重跑不满,并且随着
取
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N = 3e7 + 5;
unordered_map<int, int> sd;
bool isp[N];
int t, n, prime[N], cnt[N], d[N], tp;
void sieve(int n) {
d[1] = 1;
for(int i = 2; i <= n; i ++ ) {
if(!isp[i]) prime[ ++ tp] = i, d[i] = 2, cnt[i] = 1;
for(int j = 1; j <= tp && i * prime[j] <= n; j ++ ) {
isp[i * prime[j]] = true;
if(i % prime[j] == 0) {
cnt[i * prime[j]] = cnt[i] + 1;
d[i * prime[j]] = d[i] / (cnt[i] + 1) * (cnt[i] + 2);
break;
} else {
cnt[i * prime[j]] = 1;
d[i * prime[j]] = d[i] * d[prime[j]];
}
}
}
for(int i = 1; i <= n; i ++ ) d[i] += d[i - 1];
}
int getd(int x) {
if(x <= N - 5) return d[x];
if(sd[x]) return sd[x];
int ans = 0;
for(int i = 1, j; i <= x; i = j + 1)
j = x / (x / i), ans += (x / i) * (j - i + 1);
return sd[x] = ans;
}
int solve(int x) {
int ans = 0;
for(int i = 1, j; i <= x; i = j + 1)
j = x / (x / i), ans += (x / i) * (getd(j) - getd(i - 1));
return ans;
}
signed main() {
ios :: sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> t;
sieve(N - 5);
while(t -- ) {
cin >> n;
cout << solve(n) << endl;
}
return 0;
}