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;
}

浙公网安备 33010602011771号