zoukankan      html  css  js  c++  java
  • POJ2480:Longge's problem(欧拉函数的应用)

    题目链接:传送门

    题目需求:

     Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N. 这题就是上一篇博客的变形。

    题目解析:首先先求出与N互质的个数,即N的欧拉函数值,之后分解出N的因子来,求解方法如下。

    证明:

    要求有多少个 i 满足gcd(i, N) = d 如果gcd(i, N) = d,则gcd(i/d, N/d) = 1 由于i <= N,所以 i/d <= N/d,转化为求多少个不大于N/d的数与N/d互质,而这就是欧拉函数 所以有phi(N/d)个 i 满足gcd(i, N) = d,所以∑d*phi(N/d)即为答案。

    我搜了大部分人的题解都是利用乘性函数做的,思想我附在代码下面,因为已A,我就不用他们那种方法了。

    代码:(欧拉函数打表204ms)

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <math.h>
    typedef long long ll;
    using namespace std;
    ll phi[100005];
    ll f[10005];
    ll sum,n,t,tt,i;
    void init()
    {
        memset(phi,0,sizeof(phi));
        phi[1]=1;
        for(int i=2; i<=10000; i++)
        {
            if(!phi[i])
            {
                for(int j=i; j<=10000; j=j+i)
                {
                    if(!phi[j]) phi[j]=j;
                    phi[j]-=phi[j]/i;
                }
            }
        }
    }
    int main()
    {
        init();
        while(scanf("%I64d",&n)!=EOF)
        {
            tt=0;
            for(i=2; i*i<n; i++)
            {
                if(n%i==0)
                {
                    f[tt++]=i;
                    f[tt++]=n/i;
                }
            }
            if(i*i==n)
                f[tt++]=i;
            sort(f,f+tt);
            if(tt==0)
            {
                tt=2*n-1;
                printf("%I64d
    ",tt);
                continue;
            }
            t=n;
            sum=n;
            for(i=2; i*i<=t; i++)
            {
                if(t%i==0)
                {
                    sum-=sum/i;
                    t/=i;
                    while(t%i==0)
                        t/=i;
                }
            }
            if(t!=1)
                sum-=sum/t;
            sum+=n;
            for(i=0; i<tt; i++)
            {
                if(n/f[i]>=10000)
                {
                    ll temp=n/f[i];
                    ll cot=temp;
                    for(ll z=2; z*z<=temp; z++)
                    {
                        if(temp%z==0)
                        {
                            t/=z;
                            cot-=cot/z;
                            while(temp%z==0)
                                temp/=z;
                        }
                    }
                    if(temp!=1) cot-=cot/temp;
                    sum+=cot*f[i];
                    continue;
                }
                sum+=(phi[n/f[i]])*f[i];
            }
            printf("%I64d
    ",sum);
        }
        return 0;
    }

    下面推导没看懂。。。。。

    积性函数:若任取互质的两个数m,n,都有f(m*n) = f(m)*f(n),那么f就是积性函数

     容易证明gcd(i,n)是积性函数,即: 如果n = m1*m2 且gcd(i,m1*m2) = gcd(i,m1)*gcd(i,m2).  然后根据具体数学上的结论: 积性函数的和也是积性的,所以如果我们设所求答案是f(n) 则: f(n) = f(m1)*(m2) 其中,m1*m2 = n 且m1,m2互质

    经过因子分解,那种只要求到f(p^k)就可以利用积性把所有结果相乘得到最后答案。

    还要一个结论: f(n) = sum(p * phi(n/p))  其中p是n的因子,phi(n/p) 是从1到n有多少个数和n的gcd是p,  这个结论比较好证明的。

     所以求f(p^k)转化成求phi(p^i) i =0....k;  而根据公式phi(p^i) = (p-1)*p^(i-1)可以求出,这样整个问题就解决了。 


     

  • 相关阅读:
    webug第四关:告诉你了flang是5位数
    webug第三关:你看到了什么?
    webug第二关:从图片中你能找到什么?
    webug第一关:很简单的一个注入
    redhat-DHCP服务的配置与应用
    python-基础入门-7基础
    bWAPP----SQL Injection (GET/Search)
    ctf-web-sql
    光棍节程序员闯关秀writeup
    ajax回调函数Status问题
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4251186.html
Copyright © 2011-2022 走看看