【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;
}
posted @ 2018-06-08 15:30  sigongzi  阅读(158)  评论(0编辑  收藏  举报