https://www.acwing.com/problem/content/222/
Within seek n gcd number to the number of prime numbers.
In fact, if n and m are not the same, seemingly to do so below. I.e. n and m are not as likely to have to inversion, the following is approximately nlogn, in that for each bottleneck T brush his corresponding prime factors p mu [T / p].
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7;
int Sum[MAXN + 5];
char mu[MAXN + 5];
int p[(MAXN) / 10 + 5], ptop;
bitset < MAXN + 5 > np;
void sieve(int n = MAXN) {
np[1] = mu[1] = 1;
for(int i = 2; i <= n; i++) {
if(!np[i])
p[++ptop] = i, mu[i] = - 1;
for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
np[t] = 1;
if(i % p[j])
mu[t] = -mu[i];
else {
mu[t] = 0;
break;
}
}
}
for(int i = 1; i <= ptop; ++i) {
for(int cnt = 1, x = p[i]; x <= n; x += p[i], ++cnt) {
Sum[x] += mu[cnt];
}
}
for(int i = 1; i <= n; ++i) {
Sum[i] += Sum[i - 1];
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n;
scanf("%d", &n);
sieve(n);
ll sum = 0;
for(int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
sum += 1ll * (n / l) * (n / l) * (Sum[r] - Sum[l - 1]);
}
printf("%lld\n", sum);
}
Internet to find a strange linear screen, an eye-opener, anything can be a sieve, classify discussed in terms of the number of minimum quality factor, this solution can be solved n and m are not the same problem.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e7;
int Sum[MAXN + 5];
char mu[MAXN + 5];
int p[(MAXN) / 10 + 5], ptop;
bitset < MAXN + 5 > np;
void sieve(int n = MAXN) {
//Sum[T]表示T的所有质数因子p的mu[T/p]之和
np[1] = mu[1] = 1;
Sum[1] = 0;
for(int i = 2; i <= n; i++) {
if(!np[i]) {
p[++ptop] = i, mu[i] = - 1;
Sum[i] = mu[1];
}
for(int j = 1, t; j <= ptop && (t = i * p[j]) <= n; j++) {
np[t] = 1;
if(i % p[j]) {
mu[t] = -mu[i];
Sum[t] = -Sum[i] + mu[i];
} else {
mu[t] = 0;
//T有>=2个p
//当T有2个p时,只有除掉p可能会有结果,此时为Sum[T]=mu[y]
//当T有>=3个p时,结果都是0,此时也是Sum[T]=mu[y]
Sum[t] = mu[i];
break;
}
}
}
for(int i = 1; i <= n; ++i) {
Sum[i] += Sum[i - 1];
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int n;
scanf("%d", &n);
sieve(n);
ll sum = 0;
for(int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
sum += 1ll * (n / l) * (n / l) * (Sum[r] - Sum[l - 1]);
}
printf("%lld\n", sum);
}
But it looks like the same as m and n can be simplified. Direct Euler function gets the job done.