[题解] UVA11426 GCD - Extreme (II)

题面

莫反是不可能莫反的,这辈子都不可能莫反了

题目要求的是

\[ \sum\limits_{i=1}^n \sum\limits_{j=i+1}^n \gcd(i,j) \]

稍微变个亚子

\[ \sum\limits_{i=1}^n \sum\limits_{j=1}^{i-1} \gcd(i,j) \]

考虑求\(f(n)=\sum\limits_{i=1}^{n-1} \gcd(n,i)\)

首先\(\gcd(n,i) \mid n\),考虑枚举\(\gcd\)的值

\[ f(n)=\sum\limits_{d \mid n} d \sum\limits_{i=1}^{n-1} [\gcd(n,i)=d] \]

\(\gcd(n,i)=d\)等价于\(\gcd(\frac{n}{d},\frac{i}{d})=1\),于是

\[ \begin{aligned} f(n)&=\sum\limits_{d \mid n} d \sum\limits_{i=1}^{n-1} [\gcd(\frac{n}{d},\frac{i}{d})=1] \\ &=\sum\limits_{d \mid n} d \times \varphi(\frac{n}{d}) \end{aligned} \]

特别的,\(\varphi(1)=0\)

筛出欧拉函数,然后类似埃氏筛的枚举\(d\),更新\(d\)的倍数的\(f\)就好了。

对于\(n\)\(Ans_n=\sum\limits_{i=1}^n f(i)\),维护前缀和就好了

跑的超慢的\(Code:\) 为什么你们那么快啊...

#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<(b);i++)
#define per(i,a,b) for (int i=(a)-1;i>=(b);i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef long long ll;
typedef double db;
typedef pair<int,int> PII;
typedef vector<int> VI;

const int maxn=4e6,N=maxn+10;
ll f[N],phi[N],vis[N];
int p[N],pn;

void getphi(int n) {
    rep(i,2,n+1) {
        if(!vis[i]) {
            p[pn++]=i;
            phi[i]=i-1;
        }
        for(int j=0;j<pn&&i*p[j]<=n;j++) {
            vis[i*p[j]]=1;
            if(i%p[j]==0) {phi[i*p[j]]=phi[i]*p[j];break;}
            else phi[i*p[j]]=phi[i]*(p[j]-1);
        }
    }
}

void init() {
    getphi(maxn);
    rep(i,1,maxn+1) for(int j=i*2;j<=maxn;j+=i) 
        f[j]+=i*phi[j/i];
    rep(i,1,maxn+1) f[i]+=f[i-1];
}

int n;
int main() {
    init();
    while(scanf("%d",&n)==1&&n) printf("%lld\n",f[n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wxq1229/p/12341193.html