UVA11426 GCD - Extreme (II)

题意:输入n,问所有gcd(i, j)的和,1<=i<j<=n,2<=n<=4000000

题解:可以发现是递推得到ans[n] = ans[n-1]+f[n],f[n]就代表了n和小于n的数的gcd的和,求f[n]可以由因子推得,枚举gcdb就是n的因子,gcd(n, a) = b所以gcd(n/b, a/b) = 1就是求与n/b互质的数有几个,也就是欧拉函数,这里用因子来推,每个因子对他的倍数都有贡献,预处理一下

#include <bits/stdc++.h>
#define ll long long
#define maxn 4000100
using namespace std;
ll ans[maxn], f[maxn], phi[maxn];
void init(ll num){
    for(int i=2;i<=num;i++) phi[i] = 0;
    phi[1] = 1;
    for(int i=2;i<=num;i++){
        if(!phi[i])
        for(int j=i;j<=num;j+=i){
            if(!phi[j]) phi[j] = j;
            phi[j] = phi[j]/i*(i-1);
        }
        for(ll j=1;j*i<=num;j++)
            f[i*j] += phi[i]*j;
    }
}
int main(){
    ll n;
    init(4000000);
    for(ll i=2;i<=4000000;i++)
        ans[i] = ans[i-1]+f[i];
    while(~scanf("%lld", &n)&&n)
        printf("%lld\n", ans[n]);
    return 0;
}

 

转载于:https://www.cnblogs.com/Noevon/p/7410008.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值