POJ2480:求所有最大公因数之和(附带详细数学推导)

Description

Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N.
“Oh, I know, I know!” Longge shouts! But do you know? Please solve it.


Input
Input contain several test case.
A number N per line.


Output
For each N, output ,∑gcd(i, N) 1<=i <=N, a line


Sample Input
2
6


Sample Output
3
15


推导(其中所用欧拉函数与积性函数知识可自行查阅):

设 f ( N ) = ∑ i = 1 N g c d ( i , N ) 设f(N)=\displaystyle\sum_{i=1}^{N}{gcd_{(i,N)}} f(N)=i=1Ngcd(i,N)可知f(n)是积性函数(此处不给出证明)
不妨令N的素因子分解式N= p 1 a 1 p_{1}^{a_{1}} p1a1· p 2 a 2 p_{2}^{a_{2}} p2a2·…· p n a n p_{n}^{a_{n}} pnan p i p_{i} pi是素数)

所以由积性函数的性质可知
f ( N ) = f ( p 1 a 1 ) ⋅ f ( p 2 a 2 ) ⋅ … ⋅ f ( p n a n ) f(N)=f(p_{1}^{a_{1}})·f(p_{2}^{a_{2}})·…·f(p_{n}^{a_{n}}) f(N)=f(p1a1)f(p2a2)f(pnan)

对 f ( p 1 a 1 ) = ∑ i = 1 p 1 a 1 g c d ( i , p 1 a 1 ) 对f(p_{1}^{a_{1}})=\displaystyle\sum_{i=1}^{p_{1}^{a_{1}}}{gcd_{(i,p_{1}^{a_{1}})}} f(p1a1)=i=1p1a1gcd(i,p1a1)
p 1 a 1 p_{1}^{a_{1}} p1a1互素的数的个数有 φ \varphi φ( p 1 a 1 p_{1}^{a_{1}} p1a1)个,他们的最大公因数是1;
p 1 a 1 p_{1}^{a_{1}} p1a1的最大公因数为 p 1 p_{1} p1的数都可以写成 p 1 ⋅ k p_{1}·k p1k且k与 p 1 p_{1} p1互素,故k可以取[1, p 1 a 1 − 1 p_{1}^{a_{1}-1} p1a11]中与 p 1 p_{1} p1互素的数,而与 p 1 a 1 − 1 p_{1}^{a_{1}-1} p1a11不互素的数均为 p 1 p_{1} p1的倍数,所以满足条件的k有 φ \varphi φ( p 1 a 1 − 1 p_{1}^{a_{1}-1} p1a11)个,即和 p 1 a 1 p_{1}^{a_{1}} p1a1的最大公因数为 p 1 p_{1} p1的数有 φ \varphi φ( p 1 a 1 − 1 p_{1}^{a_{1}-1} p1a11)个;
依此类推……
p 1 a 1 p_{1}^{a_{1}} p1a1的最大公因数为 p 1 a 1 − 1 p_{1}^{a_{1}-1} p1a11的数有 φ ( p 1 ) \varphi(p_{1}) φ(p1)个。
p 1 a 1 p_{1}^{a_{1}} p1a1的最大公因数为 p 1 a 1 p_{1}^{a_{1}} p1a1的数有 φ \varphi φ(1)=1个。
将它们求和,即可得
f ( p 1 a 1 ) = 1 ⋅ φ ( p 1 a 1 ) + p 1 ⋅ φ ( p 1 a 1 − 1 ) + … + p 1 a 1 − 1 ⋅ φ ( p 1 ) + p 1 a 1 ⋅ φ ( 1 ) f(p_{1}^{a_{1}})=1·\varphi(p_{1}^{a_{1}})+p_{1}·\varphi(p_{1}^{a_{1}-1})+…+p_{1}^{a_{1}-1}·\varphi(p_{1})+p_{1}^{a_{1}}·\varphi(1) f(p1a1)=1φ(p1a1)+p1φ(p1a11)++p1a11φ(p1)+p1a1φ(1)

由欧拉函数公式 φ ( x ) = x ∏ i = 1 n ( 1 − 1 p i ) \varphi(x)=x\displaystyle\prod_{i=1}^{n}(1-\frac{1}{p_{i}}) φ(x)=xi=1n(1pi1)
(其中 p i p_{i} pi是x的所有质因数,x是不为0的整数)
所以 f ( p 1 a 1 ) = a 1 ⋅ p 1 a 1 ⋅ ( 1 − 1 p 1 ) + p 1 a 1 f(p_{1}^{a_{1}})=a_{1}·p_{1}^{a_{1}}·(1-\frac{1}{p_{1}})+p_{1}^{a_{1}} f(p1a1)=a1p1a1(1p11)+p1a1
= p 1 a 1 [ a 1 ( 1 − 1 p 1 ) + 1 ] =p_{1}^{a_{1}}[a_{1}(1-\frac{1}{p_{1}})+1] =p1a1[a1(1p11)+1]

所以 f ( N ) = f ( p 1 a 1 ) ⋅ f ( p 2 a 2 ) ⋅ … ⋅ f ( p n a n ) f(N)=f(p_{1}^{a_{1}})·f(p_{2}^{a_{2}})·…·f(p_{n}^{a_{n}}) f(N)=f(p1a1)f(p2a2)f(pnan)
= N ⋅ [ 1 + a 1 ( 1 − 1 p 1 ) ] ⋅ … ⋅ [ 1 + a n ( 1 − 1 p n ) ] N·[1+a_{1}(1-\frac{1}{p_{1}})]·…·[1+a_{n}(1-\frac{1}{p_{n}})] N[1+a1(1p11)][1+an(1pn1)]
= N ∑ i = 1 n ( 1 + a i ( 1 − 1 p i ) ) N\displaystyle\sum_{i=1}^{n}(1+a_{i}(1-\frac{1}{p_{i}})) Ni=1n(1+ai(1pi1))




解题代码如下,代码中为最大程度减少循环次数,还运用了定理:对任意正整数n,最多只有一个素因子大于 n \sqrt{n} n ,且如果有素因子大于 n \sqrt{n} n ,那么这个素因子的次数一定是1

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;

int main()
{
    int n;
    long long ans;
    while(cin>>n) {
        ans=n;
        int b=sqrt(1.0*n);//sqrt的形参是double类型的。
        for(int i=2; i<=b; i++)
        {
            if(n%i==0)//说明i是其中一个素因子
            {
                int a=0;
                while(n%i==0)//计算对应这个素因子的次数
                {
                    n/=i;
                    a++;
                }
                ans=ans+ans*a*(i-1)/i;//技巧:像此题除法一定要保证是整除
            }
        }
        if(n!=1)
            ans=ans+ans*(n-1)/n;//此处是在判断是否存在大于根号n的质因子
        cout<<ans<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值