题目大意:求值:
∑ni=1∑nj=1ϕ(gcd(ϕi,ϕj))
T<=5,N<=2∗106
思路:此题化简式子的思路相当普通,较为简单。
具体式子不再叙述,其思路是首先枚举
(gcd(ϕi,ϕj))
,其次枚举
ϕi
和
ϕj
,然后进行反演,反演过后调换指标,再进行简单的换元即可。
代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define N 2000000
#define int long long
using namespace std;
int cnt,phi[N + 5],mu[N + 5],f[N + 5],prime[N + 5],g[N + 5],n,num[N + 5];
bool not_prime[N + 5];
inline void Sieve_method(){
phi[1] = 1; mu[1] = 1; cnt = 0;
memset(not_prime,0,sizeof(not_prime));
for (int i = 2;i <= N; ++i){
if (!not_prime[i]) { prime[++cnt] = i; mu[i] = -1; phi[i] = i - 1; }
for (int j = 1;j <= cnt; ++j)
if (i * prime[j] > N) break;
else {
not_prime[i * prime[j]] = 1;
if (i % prime[j]) mu[i * prime[j]] = -mu[i],phi[i * prime[j]] = phi[i] * phi[prime[j]];
else mu[i * prime[j]] = 0,phi[i * prime[j]] = phi[i] * prime[j];
}
}
for (int i = 1;i <= N; ++i)
for (int j = i,k = 1;j <= N; j += i,++k)
f[j] += mu[i] * phi[k];
}
inline void get_G(){
memset(num,0,sizeof(num));
memset(g,0,sizeof(g));
for (int i = 1;i <= n; ++i) num[phi[i]]++;
for (int i = 1;i <= n; ++i)
for (int j = i;j <= n; j += i)
g[i] += num[j];
}
inline int gcd(int a,int b){
if (a % b == 0) return b;
return gcd(b,a % b);
}
inline void DO_IT(){
int T,ans,sum;
scanf("%d",&T);
while (T--){
scanf("%d",&n);
get_G();
ans = 0;
for (int i = 1;i <= n; ++i) ans += f[i] * g[i] * g[i];
cout<<ans<<endl;
}
}
main(){
Sieve_method();
DO_IT();
return 0;
}
总结:化式子的时候一定要仔细,考虑枚举顺序和对应的意义,枚举的时候要有技巧,一般是从外向内