【洛谷 P4213】 【模板】杜教篩(Sum)
阿新 • • 發佈:2021-09-16
#include <bits/stdc++.h> using namespace std; #define ll long long int cnt, n; map<int, long long> mpu, mpphi; int prime[10000010], mu[10000010], v[10000010], usum[10000010], phi[10000010]; ll phisum[10000010]; ll getusum(int n){ if(n <= 10000000) return usum[n]; if(mpu[n]) return mpu[n]; ll ans = 1; for(ll l = 2, r = 0; l <= n; l = r + 1){ r = n / (n / l); ans -= (r-l+1) * getusum(n / l); } return mpu[n] = ans; } ll getphisum(int n){ if(n <= 10000000) return phisum[n]; if(mpphi[n]) return mpphi[n]; ll ans = (ll)n * ((ll)n+1) / 2; for(ll l = 2, r = 0; l <= n; l = r + 1){ r = n / (n / l); ans -= (r-l+1) * getphisum(n / l); } return mpphi[n] = ans; } int T; int main(){ mu[1] = phi[1] = usum[1] = phisum[1] = 1; for(int i = 2; i <= 10000000; ++i){ if(!v[i]){ mu[i] = -1; phi[i] = i-1; prime[++cnt] = i; } usum[i] = usum[i-1] + mu[i]; phisum[i] = phisum[i-1] + phi[i]; for(int j = 1; j <= cnt && (ll)i * prime[j] <= 10000000; ++j){ v[i * prime[j]] = 1; if(i % prime[j] == 0){ phi[i * prime[j]] = phi[i] * prime[j]; break; } mu[i * prime[j]] = -mu[i]; phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } scanf("%d", &T); while(T--){ mpu.clear(); mpphi.clear(); scanf("%d", &n); printf("%lld %lld\n", getphisum(n), getusum(n)); } }