P2398 GCD SUM(欧拉函数好题!)

传送门

思路:要求出1-n内所有数对(i,j)的最大公约数和,这题与P2568 GCD十分类似,

先说下GCD那题吧,那题是求出欧拉值后用去素数乘上原互素对,得到新的数对(tx,ty)

的最大公约数就是素数了,具体可以点 here

会过来看这题,我们要求所有gcd的和,那么我们先用欧拉函数求出互素的组合,(x,y)

然后再枚举乘上g,1<=g<=n,这样gcd(x,y)=g了,具体能取的范围就是[1,n/x],所以我们

还需要用前缀和优化1-n的和,具体可以看代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 10001000;
const int inf = 0x3f3f3f3f;
const ll mod = 100000000;
int n;
ll num[maxn], sum[maxn];
void oula() {//欧拉函数求素数对个数
    for (int i = 2; i <= n; i++) {
        num[i] = i; sum[i] = sum[i - 1] + i;
    }
    for (int i = 2; i <= n; i++) {
        if (num[i] == i) {
            for (int j = i; j <= n; j += i) {
                num[j] = num[j] / i * (i - 1);
            }
        }
    }
}
int main() {
    //freopen("test.txt", "r", stdin);
    scanf("%d", &n);
    oula();
    ll ans = sum[n];//特判,(x,y)相等的情况
    for (int i = 2; i <= n; i++) {
        int d = n / i;//g可以取[1,d]
        ans += sum[d] * num[i] * 2;//互素对数目*可以取的g,再乘2(x,y),(y,x)算两对
        //假如n=7,i=3,那么素数对就有(1,3),(2,3)
        //g=1就是素数对的个数,g=2就是(2,6),(4,6),假设g=3可取,就会有(3,9),(6,9)而9>7,所以是不可取的
        //所以就是素数对个数*(1+2),而1+2可以用前缀和优化掉,也就得到了上面那个式子
    }
    cout << ans << endl;
    return 0;
}

 

posted @ 2021-05-25 11:00  cono奇犽哒  阅读(48)  评论(0编辑  收藏  举报