欧拉函数——POJ-2480

题目链接

题目要你求sigma gcd(i,N)  1<=i<=N

首先要知道一个式子gcd(i,N)=p  =>  gcd(i/p,N/p)=1

以N=12举例

gcd=1的个数就是与12互质的数字的个数,也就是12的欧拉函数值,12与1,5,7,11的gcd

gcd=2的个数包含了12/2=6的欧拉函数值,也就是12与2,10的gcd

gcd=3的个数包含了12/3=4的欧拉函数值,也就是12与3,9的gcd

这样从i=1,i*i<=n,找到n%i==0的所有i*euler(n/i)就已经找到了大部分的gcd了

剩下的则是有gcd包含了几个素数相乘

可以知道gcd(i,N)全部都是N的因子,公约数嘛

这些因子有些比√n大,有些比√n小

通过之前的式子,我们的思路是找到N所有可能的gcd=P,累加P*euler(N/P)

在我们循环i=1,i*i<=n 找到N%i==0的过程中,找到的这个i因子是小等于√N的

但是如果i*i<N,那么N/i 一定大于√N并且也是N的因子

所以循环里找到这些对应有两个因子的i 进行累加

题目代码

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
typedef long long LL;
LL euler(LL n){
    LL ans=n;
    for(LL i=2;i*i<=n;i++){
        if(n%i==0){
            ans=ans/i*(i-1);
            while(n%i==0)
                n/=i;
        }
    }
    if(n>1)
        ans=ans/n*(n-1);
    return ans;
}
int main(){
    LL n;
    while(~scanf("%lld",&n)){
        LL sum=0;
        for(LL i=1;i*i<=n;i++)
        if(n%i==0){
            sum+=i*euler(n/i);
            if(i*i<n)sum+=(n/i)*euler(i);
        }
        printf("%lld
",sum);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/helman/p/11354558.html