zoukankan      html  css  js  c++  java
  • 欧拉工程第69题:Totient maximum

    题目链接

    image

     

    欧拉函数φ(n)(有时也叫做phi函数)可以用来计算小于n 的数字中与n互质的数字的个数。

     

    当n小于1,000,000时候,n/φ(n)最大值时候的n。

     

     

    欧拉函数维基百科链接

    image

    这里的是p是n的素因子,当素因子有相同的时候只取一个

    任意一个正整数都能分解成若干个素数乘积的形式

    如下所示:

    image

     

    long phi(int n){
            long res=0;
            int pi=0;
            if(n==1) return 0;
            res = n;
            pi = 2;
            while(n!=1){
                if(n%pi==0){
                    res*=(pi-1);
                    res/=pi;
                    while(n%pi==0){
                        n/=pi;
                    }
                }
                pi++;
            }
        return res;
        }

    上面res是存放φ(n)

    是素因子的数更行res

    由于素因子可能相同的

    while(n%pi==0){
                        n/=pi;
                    }
    这里的while循环就是用来去除重复的素因子

     

    然而运行结果:

    //    510510 5.539388020833333
    //    running time=270s483ms

    这里要变量一百万次,内循环还要遍历,时间已经超过了欧拉工程的一分钟原则

    参考网上程序,改成下面的形式:

    long phi2(int n){
            long res = 0;
            if(n==1) return 0;
            int pi=2;
            res = n;
            while(pi*pi <=n){
                if(n%pi==0){
                    res*=(pi-1);
                    res/=pi;
                    while(n%pi==0){
                        n/=pi;
                    }
                    }
                pi++;
            }
            if(n>1){
                res*=(n-1);
                res/=n;
            }
            return res;
        }

    一个结束条件是while(n!=1)

    一个结束条件是while(pi*pi<=n)  n的素因子一定小于等于根号n,当pi大于根号n的时候的循环完全是拜拜浪费时间

    此时你一定想到素数的循环,这里很类似

    运行结果:

    //    510510 5.539388020833333
    //    running time=1s292ms

    时间少了很多

    在题解报告中,看到用到素数

    当这个数的是素数的时候,欧拉函数φ(n) = n-1

    当不是素数时候,找出小于n的素数,且能不n整除的数是n的素因子

     

    long phi3(int n){
            long res = n;
            int pi=2;
            if(isPrime(n)||n==1)  
                res = n-1;
            else{
                while(pi<=n){
                    if(n%pi==0 &&isPrime(pi)){
                        res*=(pi-1);
                        res/=pi;
                    }
                    pi++;
                }
    
            }
            return res;
            
        }

    结果:

    //    510510 5.539388020833333
    //    running time=1885s497ms

    上面程序对找到的素因子,没有去除,同时循环是while(pi<=n),可以进一步优化

    while(pi<=n){
                    if(n%pi==0 &&isPrime(pi)){
                        res*=(pi-1);
                        res/=pi;
                        while(n%pi==0){
                            n/=pi;
                        }
                    }
                    pi++;
                }

    结果:

    //    510510 5.539388020833333
    //    running time=111s291ms

    时间少了好多

    while(pi*pi<=n){
                    if(n%pi==0 &&isPrime(pi)){
                        res*=(pi-1);
                        res/=pi;
    //                    while(n%pi==0){
    //                        n/=pi;
    //                    }
                    }
                    pi++;
                }

    结果:

    //    510510 5.539388020833333
    //    running time=4s531ms

    然而while(pi*pi<=n) + 去除相同素因子 的,程序结果不对!!!

     

    while(pi*pi<=n){
                    if(n%pi==0 &&isPrime(pi)){
                        res*=(pi-1);
                        res/=pi;
                        while(n%pi==0){
                            n/=pi;
                        }
                    }
                    pi++;
                }
                if(n>1) res = res/n*(n-1);

    这样就对了

    结果:

    //    510510 5.539388020833333
    //    running time=1s454ms

    去重后,最后一个n也是符合条件的

     

    这个时间竟然比第2个的时间还要长。

     

    Python程序:

    import time as time
    
    def phi(n):
        if n==1 :return 0 
        res = n 
        pi = 2 
        while(pi*pi<=n):
            if n%pi==0:
                res=res/pi*(pi-1)
                while n%pi==0:
                    n/=pi 
            pi+=1
        if n>1:res=res/n*(n-1)
        return res 
    # 510510
    # running time: 32.007999897 s
    if __name__ == '__main__':
        t0 = time.time()
        Max_n = 1000000
        result= 1 
        value = 0.0
        for n in range(2,Max_n):
            euler = phi(n)
            temp = n/(euler*1.0)
            if temp>value:
                value = temp
                result = n 
        print result
        print "running time:",(time.time() - t0),'s'

    全部的Java程序:

     

    package project61;
    
    
    public class P69{
        
        void run(){
            
            long max_n = 1000000;
            double value = 0.0;
            long euler = 0;
            long N=0;
            
            for(int i=2;i<=max_n;i++){
                
                euler = phi3(i);
    //            System.out.println(i+" "+euler);
                double temp = (double)i/(euler*1.0);
                    if(temp>value){
                        value = temp;
                        N = i;
                    }
                
            }
            System.out.println(N+" "+value);
        }
        long phi3(int n){
            long res = n;
            int pi=2;
            if(isPrime(n)||n==1)  
                res = n-1;
            else{
                while(pi*pi<=n){
                    if(n%pi==0 &&isPrime(pi)){
                        res*=(pi-1);
                        res/=pi;
                        while(n%pi==0){
                            n/=pi;
                        }
                    }
                    pi++;
                }
                if(n>1) res = res/n*(n-1);
            }
            return res;
            
        }
    //    510510 5.539388020833333
    //    running time=1885s497ms
    
    //    510510 5.539388020833333
    //    running time=111s291ms
        
    //    510510 5.539388020833333
    //    running time=4s531ms
        
    //    510510 5.539388020833333
    //    running time=1s454ms
        boolean isPrime(int num){
            if(num==2||num==3||num==5||num==7) return true;
            if(num<=1||num%2==0||num%3==0) return false;
            for(int i=2;i<=Math.sqrt(num)+1;i++){
                if(num%i==0) return false;
            }
            return true;
        }
        long phi2(int n){
            long res = 0;
            if(n==1) return 0;
            int pi=2;
            int k =0;
            res = n;
            while(pi*pi <=n){
                if(n%pi==0){
                    res*=(pi-1);
                    res/=pi;
                    while(n%pi==0){
                        n/=pi;
                    }
                    }
                pi++;
            }
            if(n>1){
                res*=(n-1);
                res/=n;
            }
            return res;
        }
    //    510510 5.539388020833333
    //    running time=1s292ms
    
        long phi(int n){
            long res=0;
            int pi=0;
            if(n==1) return 0;
            res = n;
            pi = 2;
            while(n!=1){
                if(n%pi==0){
                    res*=(pi-1);
                    res/=pi;
                    while(n%pi==0){
                        n/=pi;
                    }
                }
                pi++;
            }
        return res;
        }
    //    510510 5.539388020833333
    //    running time=270s483ms
        
        public static void main(String[] args){
            long start = System.currentTimeMillis();
            new P69().run();
            long end = System.currentTimeMillis();
            long time = end - start;
            System.out.println("running time="+time/1000+"s"+time%1000+"ms");
    
        }
    }
  • 相关阅读:
    16条很有用的Chrome浏览器命令
    通用测试用例
    Vue中@click、@click.stop和@click.prevet用法
    Vue事件的函数传参
    Vue事件的基本用法
    vue中v-on和v-bind的区别
    Vue中数据的双向绑定方法
    v-once用法
    v-clock、v-text、v-html和v-pre详解
    IDEA给已有项目添加maven依赖
  • 原文地址:https://www.cnblogs.com/bbbblog/p/4824358.html
Copyright © 2011-2022 走看看