• Longge's problem poj2480 欧拉函数,gcd


    Longge's problem
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 6918   Accepted: 2234

    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

    Source

     

     

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <math.h>
     5 #include <string.h>
     6 #define MAXN 100010
     7 #define INF 0x7fffffff
     8 using namespace std;
     9 long long a[110000]= {0},b[110000],nu,c[10000][2],cn;
    10 void init()
    11 {
    12     nu=0;
    13     long long i,j;
    14     for(i=2; i<110000; i++)
    15     {
    16         if(!a[i])
    17         {
    18             b[nu++]=i;
    19             j=i*i;
    20             while(j<110000)
    21             {
    22                 a[j]=1;
    23                 j+=i;
    24             }
    25         }
    26     }
    27 }
    28 void fun(long long x)
    29 {
    30     long long i;
    31     memset(c,0,sizeof(c));
    32     cn=0;
    33     for(i=0; b[nu]<=x&&i<nu; i++)
    34     {
    35         if(x%b[i]==0)
    36         {
    37             c[cn][0]=b[i];
    38             while(x%b[i]==0)
    39             {
    40                 c[cn][1]++;
    41                 x/=b[i];
    42             }
    43             cn++;
    44         }
    45     }
    46     if(x!=1)
    47     {
    48         c[cn][0]=x;
    49         c[cn++][1]=1;
    50     }
    51 }
    52 long long so(long long n,long long x)
    53 {
    54     long long i=0,sum=n;
    55     while(x)
    56     {
    57         if(x&1)
    58         {
    59             sum=sum/c[i][0]*(c[i][0]-1);
    60             sum*=c[i][1];
    61         }
    62         i++;
    63         x>>=1;
    64     }
    65     return sum;
    66 }
    67 long long work(long long n)
    68 {
    69    long long i,size=1<<cn,sum=0;
    70    for(i=0;i<size;i++)
    71    {
    72        sum+=so(n,i);
    73    }
    74    return sum;
    75 }
    76 int main()
    77 {
    78     init();
    79     long long n;
    80     while(~scanf("%I64d",&n))
    81     {
    82         fun(n);
    83         printf("%I64d
    ",work(n));
    84     }
    85 }
    View Code

    设函数g(n) = gcd(i,n) (1<=i<=n),由积性函数的定义,g(n)=g(m1)*g(m2) (n=m1*m2 且 (m1, m2)= 1),所以g是积性函数。由具体数学上的结论,积性函数的和也是积性的。所以f(n) = ∑gcd(i, n)也是积性函数。由初等数论中的定理,如果f(n)是不恒为0的数论函数,n>1时 n=p1^a1*p2^a2*...*ps^as,那么f(n)是积性函数的充要条件是f(1)=1,及f(n) = f(p1^a1)*f(p2^a2)*...f(pr^ar)。所以只要求f(pi^ai)就好,如果d是n的一个约数,那么1<=i<=n中gcd(i,n) = d的个数是phi(n/d),即n/d的欧拉函数

    f(pi^ai) =  Φ(pi^ai)+pi*Φ(pi^(ai-1))+pi^2*Φ(pi^(ai-2))+...+pi^(ai-1)* Φ(pi)+ pi^ai *Φ(1)

         = pi^(ai-1)*(pi-1) + pi*pi^(ai-2)*(pi-1)....+pi^ai

         =  pi^ai*(1+ai*(1-1/pi))

    f(n) = p1^a1*p2^a2...*pr^ar*(1+a1*(1-1/p1))*(1+a2*(1-1/p2))*...

           =  n*(1+a1*(1-1/p1))*(1+a2*(1-1/p2))*...

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <math.h>
     5 #include <string.h>
     6 #define MAXN 100010
     7 #define INF 0x7fffffff
     8 using namespace std;
     9 int a[50000]= {0},b[50000],nu,c[70][2],cn;
    10 void init()
    11 {
    12     nu=0;
    13     long long i,j;
    14     for(i=2; i<50000; i++)
    15     {
    16         if(!a[i])
    17         {
    18             b[nu++]=i;
    19             j=i*i;
    20             while(j<50000)
    21             {
    22                 a[j]=1;
    23                 j+=i;
    24             }
    25         }
    26     }
    27 }
    28 void fun(long long x)
    29 {
    30     long long i;
    31     memset(c,0,sizeof(c));
    32     cn=0;
    33     for(i=0; b[nu]<=x&&i<nu; i++)
    34     {
    35         if(x%b[i]==0)
    36         {
    37             c[cn][0]=b[i];
    38             while(x%b[i]==0)
    39             {
    40                 c[cn][1]++;
    41                 x/=b[i];
    42             }
    43             cn++;
    44         }
    45     }
    46     if(x!=1)
    47     {
    48         c[cn][0]=x;
    49         c[cn++][1]=1;
    50     }
    51 }
    52 long long work(long long n)
    53 {
    54    long long i,sum=n;
    55    for(i=0;i<cn;i++)
    56    {
    57        sum=sum+sum*c[i][1]*(c[i][0]-1)/c[i][0];
    58    }
    59    return sum;
    60 }
    61 int main()
    62 {
    63     init();
    64     long long n;
    65     while(~scanf("%I64d",&n))
    66     {
    67         fun(n);
    68         printf("%I64d
    ",work(n));
    69     }
    70 }
    View Code
  • 相关阅读:
    【JZOJ4616】二进制的世界
    【JZOJ4665】数列
    【JZOJ4811】排队
    2017.08.19【NOIP提高组】模拟赛B组 经济编码
    浅谈匈牙利算法
    2017.08.18【NOIP提高组】模拟赛B组 恭介的法则(rule)
    2017.08.18【NOIP提高组】模拟赛B组 沙耶的玩偶(doll)
    2017.08.15【NOIP提高组】模拟赛B组 单足跳
    2017.08.15【NOIP提高组】模拟赛B组 生日聚餐
    2017.08.12【NOIP提高组】模拟赛B组 巴比伦
  • 原文地址:https://www.cnblogs.com/ERKE/p/3693313.html
Copyright © 2020-2023  润新知