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; }