51nod 1594 Gcd and Phi

题目大意:求值: ni=1nj=1ϕ(gcd(ϕi,ϕj))
T<=5,N<=2106
思路:此题化简式子的思路相当普通,较为简单。
具体式子不再叙述,其思路是首先枚举 (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;
} 

总结:化式子的时候一定要仔细,考虑枚举顺序和对应的意义,枚举的时候要有技巧,一般是从外向内

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值