【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('
')
#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;
}
原文地址:https://www.cnblogs.com/ivorysi/p/9155736.html