暴力出七级
Neutralized · · 题解
PCOPTRIP。
设
注意到集合
对于
枚举
对于
同理是
然后再做一次
因为我们的预处理是直接对每个
你会发现我们算下来貌似要跑很久,但是甚至不需要精细实现,2.8s 就飞过去了。
Sieve(100000); int T;
for(cin>>T;T--;){
cin>>n; ll res = 0;
for(int l=1,r;l<=n;l=r=r+1){
int LIM = n/l; r = n/LIM;
for(int x=1;x<=r;++x) for(int y=x;y<=r;y+=x) f[x] += mu[y];
for(int x=1;x<=r;++x){ ll d = 1ll*mu[x]*f[x]; for(int y=x;y<=n;y+=x) F[y] += d; }
for(int x=1;x<=LIM;++x){ ll d = 1ll*mu[x]*(LIM/x); for(int y=x;y<=n;y+=x) G[y] += d; }
for(int i=1;i<=n;++i) res += 1ll*G[i]*G[i]*(F[i]-lstF[i]);
copy(F+1,F+n+1,lstF+1), fill(F+1,F+n+1,0), fill(G+1,G+n+1,0), fill(f+1,f+r+1,0);
}
fill(lstF+1,lstF+n+1,0), cout<<res<<'\n';
}
能做到
如果我们只对
其中
(第一项放宽了对于
类似地可以写出
这个东西对于一个固定的
代码其实很好写,可以事先把每个数组对应的式子写出来,避免混淆。
这里放个正解的完整版代码。
#include <bits/stdc++.h>
using namespace std;
#define ep emplace_back
using ll = long long;
inline ll Sqr(int x){ return 1ll*x*x; }
constexpr int N = 100003, Q = 862;
int n, Minp[N], id[N], cnt, mu[N], R[N], B[N];
int bs[N], tot, Smu[N], F[Q][N], G[Q][N];
vector<int> pr; bitset<N> vis;
inline void Prepare(int n){
mu[1] = Smu[1] = 1;
for(int i=1;i<=n;++i) B[i] = 1;
for(int i=2;i<=n;++i){
if(!vis[i]) pr.ep(i), mu[i] = -1, Minp[i] = B[i] = i;
for(int P : pr){
int to = i*P; if(to > n) break; vis[to] = 1;
if(i%P == 0){ mu[to] = 0, B[to] = B[i]; break; }
mu[to] = -mu[i], !Minp[to] && (Minp[to] = P), B[to] = B[i]*P;
} Smu[i] = Smu[i-1] + mu[i];
}
}
inline ll Sol(){
for(int i=1;i<=cnt;++i)
fill(F[i]+1,F[i]+n+1,0), fill(G[i]+1,G[i]+n+1,0);
ll res = cnt = tot = 0;
for(int i=1;i<=n;++i) if(B[i] == i) bs[++tot] = i;
for(int l=1,r;l<=n;l=r+1)
r = n/(n/l), R[id[r] = ++cnt] = r,
F[cnt][1] = Smu[r], G[cnt][1] = r;
for(int i=1;i<=cnt;++i){
for(int j=2;j<=tot;++j){ // bs[1] = 1 with no Minp
const int x = bs[j], nxt = x/Minp[x];
F[i][x] = F[i][nxt] + F[id[R[i]/Minp[x]]][x],
G[i][x] = G[i][nxt] - G[id[R[i]/Minp[x]]][nxt];
}
}
for(int i=1;i<=cnt;++i)
for(int x=1;x<=n;++x)
res += Sqr(G[id[n/R[i]]][B[x]]) * (F[i][B[x]] - F[i-1][B[x]]);
return res;
}
main(){
ios::sync_with_stdio(0), cin.tie(0);
Prepare(100000); int T; cin>>T;
while(T--) cin>>n, cout<<Sol()<<'\n';
}
2.04s。可能是我的实现不够精细。