luogu P4213 【模板】杜教筛(Sum)
Code:
#include <bits/stdc++.h> #include <tr1/unordered_map> using namespace std; using namespace tr1; #define ll long long #define setIO(s) freopen(s".in","r",stdin) #define maxn 5000009 #define N 2147483647 #define ull unsigned long long ull phi[maxn],mu[maxn],prime[maxn]; int vis[maxn]; int tot; void init(){ vis[1] =1, mu[1] = 1,phi[1] = 1; for(int i = 2;i < maxn; ++i) { if(!vis[i]) mu[i] = -1,phi[i] = i - 1, prime[++tot] = i; for(int j = 1;j <= tot&&prime[j]*i < maxn; ++j) { vis[prime[j]*i] = 1; if(i % prime[j]!=0) phi[i * prime[j]] = (prime[j]-1) * phi[i],mu[i*prime[j]]=-mu[i]; else { phi[i*prime[j]]=phi[i]*prime[j]; mu[i*prime[j]]=0; break; } } } for(int i = 1;i < maxn; ++i) mu[i] += mu[i-1],phi[i]+=phi[i-1]; } unordered_map<int,ull>ansmu,ansphi; inline ll get_mu(int n){ if(n < maxn) return mu[n]; if(ansmu[n]) return ansmu[n]; ll ans = 0; for(int l = 2,r;r < N && l <= n;l = r + 1) r = n / (n / l),ans += (r - l + 1) * get_mu(n/l); return ansmu[n] = 1ull-ans; } inline ll get_phi(int n){ if(n < maxn) return phi[n]; if(ansphi[n]) return ansphi[n]; ll ans = 0; for(int l = 2,r;r < N&&l<=n;l = r + 1) r = n / (n / l),ans += (r - l + 1) * get_phi(n / l); return ansphi[n]=(ull)n*(n+1ll)/2ll-ans; } int main(){ //setIO("input"); init(); int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); printf("%lld %lld\n",get_phi(n),get_mu(n)); } return 0; }