关于1-n任意的gcd的和

gcd和

题目

GCD sum
公约数的和
大意是让你求1-n任意两个数的gcd的和之类的。

解法

显然你需要枚举对吧,不然你怎么可能求出gcd呢?
其次我们需要一些数学推理
令F(n)表示\(\sum_{i=1}^{n}gcd(1,n)\)
则我们只需要求出\(2\times \sum_{i=1}^{n}F(i) + \sum_{i=1}^{n}i\)对吧。
那么成立的充要条件是\(gcd(a/d,b/d)=1\),则我们就知道\(gcd(a/d,b/d)*d=gcd(a,b)\)
那么所以我们需要求出有多少个1-n/d的互质的数,显然这就是欧拉函数
所以我们就有了如下两道题目代码

//code 1
#include<bits/stdc++.h>
#define int long long //还是自觉换long long 更好吧
using namespace std;
const int maxn=100000+5;
int phi[maxn];
int f[maxn];
int s[maxn];
void get(int n) {
    for(int i=2; i<=n; i++) phi[i]=0;
    phi[1]=1;
    for(int i=2; i<=n; i++) {
        if(!phi[i]) {
            for(int j=i; j<=n; j+=i) {
                if(!phi[j]) phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}
main() {
    int n;
    cin>>n;
    get(n);
    for(int i=1; i<=n; i++)
        for(int j=i*2; j<=n; j+=i)
            f[j]+=i*phi[j/i];
    for(int i=1; i<=n; i++) s[i]=s[i-1]+f[i];
    cout<<s[n]*2+(1+n)*n/2;
    return 0;
}
//code 2
#include<bits/stdc++.h>
#define int long long //还是自觉换long long 更好吧
using namespace std;
const int maxn=2000000+5;
int phi[maxn];
int f[maxn];
int s[maxn];
void get(int n) {
    for(int i=2; i<=n; i++) phi[i]=0;
    phi[1]=1;
    for(int i=2; i<=n; i++) {
        if(!phi[i]) {
            for(int j=i; j<=n; j+=i) {
                if(!phi[j]) phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}
main() {
    int n;
    cin>>n;
    get(n);
    for(int i=1; i<=n; i++)
        for(int j=i*2; j<=n; j+=i)
            f[j]+=i*phi[j/i];
    for(int i=1; i<=n; i++) s[i]=s[i-1]+f[i];
    cout<<s[n];
    return 0;
}
posted @ 2018-10-31 22:02  _Lancy  阅读(637)  评论(0编辑  收藏  举报