【51nod】1594 Gcd and Phi
题解
跟随小迪学姐的步伐,学习一下数论
小迪学姐太巨了!
这道题的式子很好推嘛
\(\sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{d|\phi(i),\phi(j)} \phi(d) [gcd(\frac{\phi(i)}{d},\frac{\phi(j)}{d}) == 1]\)
\(\sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{d|\phi(i),\phi(j)} \phi(d) \sum_{t | \frac{\phi(i)}{d},\frac{\phi(j)}{d}} \mu(t)\)
\(\sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{T|\phi(i),\phi(j)} \sum_{d|T}\phi(d)\mu(\frac{T}{d})\)
设\(g(T) = \sum_{d|T}\phi(d)\mu(\frac{T}{d})\)
\(\sum_{i = 1}^{n} \sum_{j = 1}^{n} \sum_{T|\phi(i),\phi(j)} g(T)\)
设\(f(T) = \sum_{i = 1}^{n} \phi(i) == T\)
那么最后的答案就是
\(\sum_{T = 1}^{n} g(T) [\sum_{T|k} f(k)]^2\)
复杂度\(O(n \log n)\)
代码
#include <bits/stdc++.h>
#define MAXN 2000005
//#define ivorysi
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eps 1e-8
#define pii pair<int,int>
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int T,N;
int64 phi[MAXN],mu[MAXN],f[MAXN],g[MAXN];
bool nonprime[MAXN];
int prime[MAXN],tot;
void Solve() {
read(N);
int64 ans = 0;
memset(f,0,sizeof(f));
for(int i = 1 ; i <= N ; ++i) f[phi[i]]++;
for(int i = 1 ; i <= N ; ++i) {
int64 s = 0;
int t = i;
while(t <= N) s += f[t],t += i;
ans += g[i] * s * s;
}
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
read(T);
mu[1] = 1;
phi[1] = 1;
for(int i = 2 ; i <= 2000000 ; ++i) {
if(!nonprime[i]) {
prime[++tot] = i;
phi[i] = i - 1;
mu[i] = -1;
}
for(int j = 1 ; j <= tot ; ++j) {
if(prime[j] > 2000000 / i) break;
nonprime[i * prime[j]] = 1;
if(i % prime[j] == 0) phi[i * prime[j]] = phi[i] * prime[j],mu[i * prime[j]] = 0;
else phi[i * prime[j]] = phi[i] * (prime[j] - 1),mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1 ; i <= 2000000 ; ++i) {
int t = i;
while(t <= 2000000) {
g[t] += phi[i] * mu[t / i];
t += i;
}
}
while(T--) {
Solve();
}
return 0;
}