这是我的代码(按照官方题解数论分块套杜教筛的思路写的):
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int SqrtN = 15e5 + 9,MOD = 998244353;
int n,v;
bool is_not_prime[SqrtN] = {1,1};
int prime[SqrtN],top;
int mu[SqrtN],sum_mu[SqrtN];
int ans;
void sieve(){
v = 15e5;
mu[1] = 1;
for(int i = 2;i <= v;i++){
if(!is_not_prime[i]){
prime[++top] = i;
mu[i] = -1;
}
for(int j = 1;j <= top && i * prime[j] <= v;j++){
is_not_prime[i * prime[j]] = 1;
if(i % prime[j] == 0)
break;
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i <= v;i++)
sum_mu[i] = sum_mu[i - 1] + mu[i];
}
unordered_map<int,int> s_mu;
int SumMu(int n){
if(n <= v)
return sum_mu[n];
if(s_mu[n])
return s_mu[n];
int ret = 1;
for(int l = 2,r;l <= n;l = r + 1){
r = n / (n / l);
ret -= (r - l + 1) * SumMu(n / l);
}
return s_mu[n] = ret;
}
int qpow(int x,int y,int MOD){
int ret = 1;
while(y){
if(y & 1)
ret = ret * x % MOD;
x = x * x % MOD;
y >>= 1;
}
return ret;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n;
sieve();
for(int l = 1,r;l <= n;l = r + 1){
r = n / (n / l);
ans = (ans + (SumMu(r) - SumMu(l - 1) + MOD) % MOD * qpow(n / l,3,MOD)) % MOD;
}
cout << ans;
return 0;
}
我不知道为什么复杂度为 O(n32)(别告诉我复杂度是直接数论分块复杂度乘杜教筛的复杂度),但实测告诉我很有可能根记忆化有关,求大佬解答。