# 51 nod 1188 最大公约数之和 V2（狄利克雷卷积+线性筛法）

### 题目大意：

i<ni=1nj=i+gcd(i,j)$\sum_{i = 1}^{i < n} \sum_{j = i +１}^{n}gcd(i, j)$
1<=n<=5000000,1<=T<=50000

### 吹水：

51 nod没良心，本来O(n log n)可以过的，可是不知为什么现在跑得这么慢，我把老曹的标再交了一次也T了3个点，于是强行推了O(n)的做法。

### 方法一：

ji=1i1j=1gcd(i,j)$\sum_{i = 1}^j \sum_{j = 1}^{i - 1} gcd(i, j)$
=ji=1ij=1gcd(i,j)ni=1gcd(i,i)$=\sum_{i = 1}^j \sum_{j = 1}^{i} gcd(i, j) - \sum_{i = 1}^n gcd(i, i)$

ji=1ij=1gcd(i,j)$\sum_{i = 1}^j \sum_{j = 1}^{i} gcd(i, j)$
=ni=1φ(i)n/i(n/i+1)/2$=\sum_{i = 1}^n φ(i) * \lfloor n / i \rfloor * (\lfloor n / i \rfloor + 1) / 2$

O(T n$\sqrt n$)

T了#17 - 25.

### 方法二：

f(i)=i1j=1gcd(i,j)$f(i) = \sum_{j = 1}^{i - 1} gcd(i, j)$

i = 1 to n
j = 2 to n / i
f(i * j)　＋＝　φ(j) * i

### 方法三：

f(i)=i1j=1gcd(i,j)$f(i) = \sum_{j = 1}^{i - 1} gcd(i, j)$

ij=1gcd(i,j)$\sum_{j = 1}^i gcd(i, j)$

=d|idφ(i/d)$= \sum_{d | i} d *φ(i / d)$

f(pq)$f(p^q)$
=qk=0pkφ(pqk)$=\sum_{k = 0}^q p^k *φ(p^{q -k })$
=(q1k=0pk(pqkpqk1))+pq$= (\sum_{k = 0}^{q - 1} p^k*(p^{q-k} - p^{q-k-1})) + p ^ q$
=(q1k=0pqpq1)+pq$= (\sum_{k = 0}^{q - 1} p^q - p^{q - 1}) + p^q$
=q(pqpq1)+pq$=q * (p^q - p^{q - 1}) + p ^ q$

#include<cstdio>
#define N 5000000
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
long long f[N + 5];
int n, T, x[N + 5], y[N + 5], p[348514];
bool bz[N + 5];
int main() {
f[1] = 1;
fo(i, 2, N) {
if(!bz[i]) p[++ p[0]] = i, x[i] = 1, y[i] = i, f[i] = 2 * i - 1;
fo(j, 1, p[0]) {
int k = i * p[j]; if(k > N) break;
bz[k] = 1;
if(!(i % p[j])) {
x[k] = x[i] + 1;
y[k] = y[i] * p[j];
f[k] = f[k / y[k]] * (x[k] * (y[k] - y[k] / p[j]) + y[k]);
break;
}
x[k] = 1;
y[k] = p[j];
f[k] = f[i] * f[p[j]];
}
}
fo(i, 1, N) f[i] = f[i - 1] + f[i] - i;
for(scanf("%d", &T); T; T --)
scanf("%d", &n), printf("%lld\n", f[n]);
}


#include<cstdio>
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const int Maxn = 5000000;
long long ans[Maxn + 5];
int n, T, p[400000], phi[Maxn + 5];
bool bz[Maxn + 5];

int main() {
phi[1] = 1;
fo(i, 2, Maxn) {
if(!bz[i]) p[++ p[0]] = i, phi[i] = i - 1;
fo(j, 1, p[0]) {
int k = i * p[j]; if(k > Maxn) break;
bz[k] = 1;
if(!(i % p[j])) {
phi[k] = phi[i] * p[j];
break;
}
phi[k] = phi[i] * (p[j] - 1);
}
}
fo(i, 1, Maxn) fo(j, 2, Maxn / i) ans[i * j] += i * phi[j];
fo(i, 2, Maxn) ans[i] = ans[i - 1] + ans[i];
printf("%d\n", ans[9]);
for(scanf("%d", &T); T; T --)
scanf("%d", &n), printf("%lld\n", ans[n]);
}

#include<cmath>
#include<cstdio>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;

const ll Maxn = 5000000;
int n, T, p[400000];
ll phi[Maxn + 5];
bool bz[Maxn + 5];

int main() {
phi[1] = 1;
fo(i, 2, Maxn) {
if(!bz[i]) p[++ p[0]] = i, phi[i] = i - 1;
fo(j, 1, p[0]) {
int k = i * p[j];
if(k > Maxn) break;
bz[k] = 1;
if(i % p[j] == 0) {
phi[k] = phi[i] * p[j];
break;
}
phi[k] = phi[i] * (p[j] - 1);
}
}
fo(i, 1, Maxn) phi[i] = phi[i - 1] + phi[i];
for(scanf("%d", &T); T; T --) {
ll ans = 0;
scanf("%d", &n);
fo(i, 1, n)  {
int j = n / (n / i);
ans += (phi[j] - phi[i - 1]) * (n / i) * (n / i + 1) / 2;
i = j;
}
ans -= (ll) n * (n + 1) / 2;
printf("%lld\n", ans);
}
}

• 本文已收录于以下专栏：

举报原因： 您举报文章：51 nod 1188 最大公约数之和 V2（狄利克雷卷积+线性筛法） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)