solution
杜 教 筛 模 板 题 杜教筛模板题 杜教筛模板题
code
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
typedef long long ll;
const double eps = 1e-7;
const int MOD = 1e9 + 7;
const int N = 5e6 + 10;
int prime[N], cnt;
ll phi[N], mu[N];
map<int, ll> s_mu;
map<int, ll> s_phi;
bool vis[N];
void get_all(int n) {
mu[1] = phi[1] = 1;
for(int i = 2; i <= n; ++ i) {
if(!vis[i]) prime[++ cnt] = i, phi[i] = i - 1, mu[i] = -1;
for(int j = 1; j <= cnt && prime[j] * i <= n; ++ j) {
vis[i * prime[j]] = true;
if(i % prime[j] == 0) {
phi[i * prime[j]] = phi[i] * prime[j];
mu[i * prime[j]] = 0;
break;
} else {
phi[i * prime[j]] = phi[i] * (prime[j] - 1);
mu[i * prime[j]] = -mu[i];
}
}
}
for(int i = 1; i <= n; ++ i) {
mu[i] += mu[i - 1];
phi[i] += phi[i - 1];
}
}
inline ll get_s_phi(ll n) {
if(n <= N) return phi[n];
if(s_phi[n]) return s_phi[n];
ll ans = (1ll + n) * n / 2;
for(ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ans -= 1ll * (r - l + 1) * get_s_phi(n / l);
}
return s_phi[n] = ans;
}
inline ll get_s_mu(ll n) {
if(n <= N) return mu[n];
if(s_mu[n]) return s_mu[n];
ll ans = 1;
for(ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
ans -= 1ll * (r - l + 1) * get_s_mu(n / l);
}
return s_mu[n] = ans;
}
void solve(ll n) {
get_all(N - 1);
printf("%lld %lld\n", get_s_phi(n), get_s_mu(n));
}
int main() {
int o;
scanf("%d", &o);
while(o --) {
ll n;
scanf("%lld", &n);
solve(n);
}
return 0;
}