GCD - Extreme (II)

本文介绍了一种使用欧拉函数和动态规划方法高效计算从1到n的所有整数与其后的每个整数之间的最大公约数之和的算法。通过预处理和累积和技巧,避免了直接调用gcd函数带来的超时问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                       


题意大概就如代码上所说的,

G=0; 
for(i=1;i<N;i++)
for(j=i+1;j<=N;j++)
{
                  G+=gcd(i,j);
}

/*Here gcd() is a function that finds the greatest common divisor of the two input numbers*/ 

/*这里gcd()是一个函数,二者中最大的公约数,输入数字*/

求i从1到n-1分别与i+1到n的最大公约数的和。

可以倒过来思考,就是求i从1到n-1与的最大公约数,(n的变化为1到n);


 n每增加一个1,循环就多一个  \large \sum _{i=1}^{n}(i,n+1);可用公式表示。

 G(n)=G(n-1)+  \large \sum _{i=1}^{n-1}(i,n);

所以重点是求   \large \sum _{i=1}^{n-1}(i,n);     这里可用for循环打个表,记录下n从1到 4000001的前缀和,最后直接输出即可。

虽说这里是求最大公约数,但直接用gcd(),还是容易超时,这里可以用欧拉函数dp[n]的方法来间接求最大公约数。

可知 gcd(i,n)=1,(i和n均为素数),

当i和n的最大公约数为k的时候,即gcd(i,n)=k,可以这样写   gcd(i/k,n/k)=1;

所以求出,每个数的欧拉函数,再遍历k的值,使得  dp[i*k]*k,

当n为素数的时候,   \large \sum _{i=1}^{n-1}(i,n);=n-1;前面的数和它的最大公约数均为1,故累加得n-1,

代码如下:

#include<stdio.h>
#include<string.h>
#define LL long long
const int N=4e6+10;
LL dp[N];
LL a[N];
void init()
{
     memset(dp,0,sizeof(dp));
    dp[1]=1;
    for(int i=2; i<=N; i++)//欧拉函数打表
    {
        if(!dp[i])
        {
            dp[i]=i-1;
            for(int j=2*i; j<=N; j+=i)
            {
                if(!dp[j])
                    dp[j]=j;
                dp[j]=dp[j]/i*(i-1);
            }
        }
        for(int j=1;i*j<=N;j++)//设公约数为j,
            a[i*j]+=dp[i]*j;
    }
    //for(int i=1;i<=30;i++)
     //   printf("%d\t",dp[i]);
}

  int main()
{
    LL n;
    init();
    for(int i=1; i<=N; i++)
        a[i]+=a[i-1];


    while(~scanf("%lld",&n)&&n)
        printf("%lld\n",a[n]);
        return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值