POJ - 2480 Longge's problem

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

題意:∑gcd(i, N) 1<=i <=N,就這個公式,給你一個n,讓你求sum=gcd(1,n)+gcd(2,n)+gcd(3,n)+…………gcd(n-1,n)+gcd(n,n),(1<=n<2^31)是多少?

 

 

歐拉函數

轉https://www.cnblogs.com/handsomecui/p/4755455.html

在數論中,對於正整數N,少於或等於N ([1,N]),且與N互質的正整數(包括1)的個數,記作φ(n)。

     φ函數的值:

    φ(x)=x(1-1/p(1))(1-1/p(2))(1-1/p(3))(1-1/p(4))…..(1-1/p(n)) 其中p(1),p(2)…p(n)爲x

的所有質因數;x是正整數; φ(1)=1(唯一和1互質的數,且小於等於1)。注意:每種質因數只有一個。

     例如:

         φ(10)=10×(1-1/2)×(1-1/5)=4;

         1 3 7 9

         φ(30)=30×(1-1/2)×(1-1/3)×(1-1/5)=8;

         φ(49)=49×(1-1/7)=42;

歐拉函數的性質:

(1)   p^k型歐拉函數:

若N是質數p(即N=p), φ(n)= φ(p)=p-p^(k-1)=p-1。

若N是質數p的k次冪(即N=p^k),φ(n)=p^k-p^(k-1)=(p-1)p^(k-1)。

(2)mn型歐拉函數

設n爲正整數,以φ(n)表示不超過n且與n互素的正整數的個數,稱爲n的歐拉函數值。若m,n互質,φ(mn)=(m-1)(n-1)=φ(m)φ(n)。

(3)特殊性質:

若n爲奇數時,φ(2n)=φ(n)。

對於任何兩個互質 的正整數a,n(n>2)有:a^φ(n)=1 mod n (恆等於)此公式即 歐拉定理

當n=p 且 a與素數p互質(即:gcd(a,p)=1)則上式有: a^(p-1)=1 mod n (恆等於)此公式即 費馬小定理

 

同餘定理:

     如果 a mod b = c 則有(a+kb) mod b =c(k爲非0整數)

     如果 a mod b = c 則有(ka) mod b =kc (k爲正整數)

     (a+b) mod c =((a mod c)+(b mod c )) mod c;

     (a*b) mod c=((a mod c)*(b mod c)) mod c

 

 

phi(n/i)則爲和n最大公約數爲i的個數 
素數p的歐拉函數值爲p-1;

 

歐拉函數模板

複製代碼
int phi(int n)//直接求 
{
    int t=n;
    for(int i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            t=t/i*(i-1);
            
            while(n%i==0) n/=i;
        }
    }
    if(n>1) t=t/n*(n-1);
    return t;
}
int p[1000001];
void init()//打表 
{
    memset(p,0,sizeof(p));
    p[1]=1;
    for(int i=2;i<1000000;i++)
    {
        if(p[i]==0)
        {
            for(int j=i;j<1000000;j+=i)
            {
                if(p[j]==0)
                p[j]=j;
                
                p[j]=p[j]/i*(i-1);
            }
        }
    }
}
複製代碼

題解

複製代碼
#include<iostream>
#include<stdio.h>
#define ll long long
using namespace std;
ll phi(int n)
{
    ll res=n;
    for(ll i=2;i*i<=n;i++)
    {
        if(n%i==0)
        {
            res=res/i*(i-1);
            while(n%i==0)n/=i;
        }
    }
    if(n>1) res=res/n*(n-1);
    return res;
 } 
 int main()
{
    ll n;
    while(scanf("%lld",&n)!=EOF)
    {
        ll ans=0;
        for(ll i=1;i*i<=n;i++)//這裏是循環了logn
        {
            if(n%i==0)
            {
                ans+=i*phi(n/i);//phi(n/i)則爲和n最大公約數爲i的個數 
                if(i*i!=n)//讓其不重複
                {
                    ans+=n/i*phi(i);//和n最大公約數爲n/i的個數
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
複製代碼

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章