【模板】杜教篩(Sum)
阿新 • • 發佈:2022-03-09
\(\text{Code}\)
#include<cstdio> #include<tr1/unordered_map> #define LL long long using namespace std; const int M = 5e6; int vis[M + 5],p[M + 5],tot,T,n; LL phi[M + 1],mu[M + 1]; tr1::unordered_map<int,LL> fm,fp; void init() { mu[1] = phi[1] = 1LL; for (int i = 2; i <= M; i++) { if (!vis[i]) p[++tot] = i,mu[i] = -1,phi[i] = i - 1; for (int j = 1; j <= tot && p[j] * i <= M; j++) { vis[p[j] * i] = 1; if (i % p[j] == 0) {phi[i * p[j]] = phi[i] * p[j]; break;} mu[p[j] * i] = -mu[i],phi[i * p[j]] = phi[i] * phi[p[j]]; } } for (int i = 1; i <= M; i++) mu[i] += mu[i - 1],phi[i] += phi[i - 1]; } LL getmu(int x) { if (x <= M) return mu[x]; if (fm[x]) return fm[x]; LL res = 1LL; for (LL l = 2,r; l <= x; l = r + 1) r = x / (x / l),res -= (LL)(r - l + 1) * getmu(x / l); return fm[x] = res; } LL getp(int x) { if (x <= M) return phi[x]; if (fp[x]) return fp[x]; LL res = (LL)x * (x + 1LL) / 2; for (LL l = 2,r; l <= x; l = r + 1) r = x / (x / l),res -= (LL)(r - l + 1) * getp(x / l); return fp[x] = res; } int main() { init(),scanf("%d",&T); for (; T; T--) scanf("%d",&n),printf("%lld %lld\n",getp(n),getmu(n)); }