洛谷P4213(杜教筛)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e6 + 3;
int t, n, cnt;
bool v[maxn];
short mu[maxn];
int isp[maxn], phi[maxn];
LL sum1[maxn];
int sum2[maxn];
unordered_map<int,LL> dp1;
unordered_map<int,int> dp2;
void init() {
mu[1] = phi[1] = 1;
for(int i = 2; i < maxn; ++i) {
if(!v[i]) {
v[i] = 1;
mu[i] = -1;
phi[i] = i - 1;
isp[cnt++] = i;
}
for(int j = 0; j < cnt && i * isp[j] < maxn; ++j) {
v[i*isp[j]] = 1;
mu[i*isp[j]] = -mu[i];
if(i % isp[j] == 0) {
mu[i*isp[j]] = 0;
phi[i*isp[j]] = phi[i] * isp[j];
break;
}
phi[i*isp[j]] = phi[i] * (isp[j] - 1);
}
}
for(int i = 1; i < maxn; ++i) sum1[i] = sum1[i-1] + phi[i], sum2[i] = sum2[i-1] + mu[i];
}
LL getnum1(int x) {
if(x < maxn) return sum1[x];
if(dp1[x]) return dp1[x];
LL ans = 1LL * x * (x + 1) / 2;
for(int l = 2, r; l <= x; l = r + 1) {
r = x / (x / l);
ans = ans - 1LL * (r - l + 1) * getnum1(x/l);
}
return dp1[x] = ans;
}
LL getnum2(int x) {
if(x < maxn) return sum2[x];
if(dp2[x]) return dp2[x];
LL ans = 1;
for(int l = 2, r; l <= x; l = r + 1) {
r = x / (x / l);
ans = ans - 1LL * (r - l + 1) * getnum2(x/l);
}
return dp2[x] = ans;
}
int main() {
init();
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
printf("%lld %lld\n", getnum1(n), getnum2(n));
}
return 0;
}
版权声明:本文允许转载,转载时请注明原博客链接,谢谢~