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

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/10540856.html