鱼C论坛

 找回密码
 立即注册
楼主: 欧拉计划

题目5:找出最小的能被1-20中每个数整除的数

[复制链接]
发表于 2018-12-19 16:29:40 | 显示全部楼层

这个FOR 要运行很久。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-2-19 17:50:33 | 显示全部楼层
对于这个题,感觉可以由几种方面来减少运行时间,
第一就是要判断的数的选择,一个个往上加和一次加20,再对比求最大公约数求值最后时间会有很大不同
第二,优先用后面的去判断,能被20整除的一定能被2,4,5,10都整除,如果后面大的都不对,及早break,减少判断次数
第三,虽然我的代码不长,但是其中还有极大修改余地,尤其是数的选择,还能改进
#include<iostream>
using namespace std;
int main(){
        int num,temp=1;
        int i=20,j;
        while(i+=20){
                j=20;
                temp=1;
                for(j;j>2;j--){
                        if(i%j!=0){
                                temp=0;
                                break;
                        }
                }
                if(temp){
                        cout<<i;
                        break;
                }
        }
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-4-10 10:04:38 | 显示全部楼层
质子列表:[2, 2, 5, 19, 3, 3, 17, 2, 2, 7, 13, 11]
返回结果:232792560
用时:0.1092007s (实测:1000内基本时间不变,10000大概3.9s)



import time

#  获取num的质子列表
def get_primelist(num):
    num_list = []
    for i in range(2, num+1):
        while num % i == 0:
            num_list.append(i)
            num = num//i
    return num_list


# 判断范围内每个质子列表的值是不是已经存在,并且对数量进行比对,多则忽略少则补齐
def get_max(MAX_NUM):
    final_list = []
    result = 1
    for i in range(MAX_NUM):
        cur_num = get_primelist(MAX_NUM - i)
        for each in cur_num:
            x = final_list.count(each)
            y = cur_num.count(each)
            if x > y:
                pass
            else:
                for z in range(y - x):
                    final_list.append(each)
                cur_num.remove(each)
    print(final_list)
    for each in final_list:
        result *= each
    return result

print(get_max(100))
print(time.process_time())
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-5-26 20:13:14 | 显示全部楼层
  1. import time as t
  2. start = t.perf_counter()
  3. i = j = 11*13*17*19
  4. list1 = [12,14,15,16,18,20]
  5. s = 1
  6. while s:
  7.     for each in list1:
  8.         if i % each != 0:
  9.             i += j
  10.             s = 1
  11.             break
  12.         else:
  13.             s = 0
  14. end = t.perf_counter()
  15. print(i)
  16. print(end - start)
复制代码

232792560
0.0015221600000000016
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-8-3 10:33:36 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2020-7-23 15:14 编辑

Python
  1. from math import gcd
  2. res = i = 1

  3. while i <= 20:
  4.     res *= i // gcd(res, i)
  5.     i += 1

  6. print(res)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-4 16:21:12 | 显示全部楼层
  1. # 两个数的最大公约数
  2. def func(a, b):
  3.     if a == 0:
  4.         return b
  5.     else:
  6.         if b > a:
  7.             a, b = b, a
  8.         a = a % b
  9.         return func(a, b)

  10. # 两个数的最小公倍数
  11. def func1(a, b):
  12.     return a * b / func(a, b)

  13. # 一个区间的最小公倍数
  14. def func2(a=1, b=20):
  15.     c = 1
  16.     for a in range(a, b+1):
  17.         c = func1(a, c)
  18.     return c

  19. print(func2(1,20))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-9 08:28:10 | 显示全部楼层
#include <stdio.h>

void main(){
        //2520是最小的能够被1到10整除的数。
        //最小的能够被1到20整除的正数是多少?
        int i=1;
        while(1){//1到正无穷的循环,用来找出结果
                int j,flag=1;
                for(j=1;j<=10;j++){//1到10
                        if(i%j!=0){//这个数不能整除1到10跳出for循环,令标志为假。下面不输出i,也不跳出while循环
                                flag=0;
                                break;
                        }       
                }
                if(flag){
                        printf("%d",i);
                        break;
                }
                i++;
        }
       
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-20 22:39:00 | 显示全部楼层
//!!!求能被1-20整除的最小正整数就是求1-20内所有数的最小公倍数!!!
//最小公倍数 = 所有数公有的质因数的最大次方 * 每个数独有的质因数的最大次方
//2520 = 2 ^ 3 * 3 ^ 2 * 5 * 7

#include <stdio.h>
#include <string.h>
#include <math.h>

#define MAX 20  //修改MAX的值可以求任意1-MAX中的最小公倍数

void prime_factor(int i, int (*pfactor)[2]);//求1-20内每一个数的质因数

void prime_factor(int i, int (*pfactor)[2])
{
        int j = 2, k = 0;
        int count = 0;

        do
        {
                if(i % j == 0)//如果i % j == 0 说明j是i的质因数中的一个
                {
                        i /= j;
                        count++;//记录质因数j出现的次数

                        pfactor[k][0] = j;//存放i的质因数j
                        pfactor[k][1] = count > pfactor[k][1] ? count: pfactor[k][1];//存放质因数j的最大次方
                }
                else
                {
                        j++;
                        k++;
                        count = 0;
                }
        }
        while(i != 1);
}

int main(void)
{
        int i;
        unsigned int result = 1;
        int pfactor[MAX][2] = {0};//pfactor[][0] 存放质因数     pfactor[][1] 存放这个质因数出现的最大次方

        for(int i = 0; i < MAX; i++)//将pfactor每一项初始化为1
        {
                pfactor[i][0] = 1;
                pfactor[i][1] = 1;
        }

        for(i = 2; i <= MAX; i++)
        {
                prime_factor(i, pfactor);
        }

        for(int i = 0; i < MAX; i++)
        {
                result *= pow(pfactor[i][0], pfactor[i][1]);//result = 所有质因数的最大次方之积
        }

        printf("result = %u\n", result);

        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-25 16:43:20 | 显示全部楼层
#include <stdio.h>
#define NUM 20

int main(){
        int num = NUM;
        int i;
        int array1[num];
        int array2[num];
        //初始化数组       
        for (i = 0;i<num;i++){
                if (i == 0){
                        array1[i]=1;
                }else{
                        array1[i] = array1[i-1] + 1;
                }
        }
        //找NUM以内的素数
        int k = 0;
        int j;
        for (j = num;j>=2;j--){
                int flag = 1;
                for(i=2;i<j;i++){
                        if (j % i == 0){
                                flag = 0;
                                break;
                        }
                }
                if (flag){
                        array2[k++] = j;
                }
       
        }
        //用短除法的方式求最小公倍数
        long long result = 1;

        while(1){
                for(j=0;j<k;j++){
                        int flag = 0;
                        for (i = 0;i < num;i++){
                                if(array1[i] % array2[j] == 0){
                                        array1[i] /= array2[j];
                                        flag = 1;
                                }
                        }
                        if (flag){
                                result = result * array2[j];
                        }

                }
                int count = 0;
                for(i=0;i<num;i++){
                        if (array1[i]==1){
                                count++;
                        }
                }
                if (count == num){
                        break;               
                }

        }
        printf("%ld\n",result);

        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-1-25 16:43:54 | 显示全部楼层
#include <stdio.h>
#define NUM 20


long gcd(long long,long long );

int main(){
        long long result = 1;
        long i = 2;
        while(i<=NUM){
                result = result * i / gcd(result,i);
                printf("i = %ld\n",i);
                i++;
        }
        printf("result = %ld\n",result);

        return 0;
}
long gcd(long long a,long long b){
        long temp;
        while(b != 0){
                temp = a;
                a = b;
                b = temp % b;
        }
               
        return a;

}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-12 18:28:20 | 显示全部楼层
很多欧拉计划中解题方法都可以用质数来求解
感觉最简单的算法,速度应该是最快的
10: 2520
20:answer:232792560
30:answer:2329089562800
40:answer:5342931457063200
  1. typedef long long ElementType;
  2. void getMinNumberOfFlag( ElementType *answer, int flag)
  3. {
  4.     int array[flag] = {0};
  5.     int temp[flag] = {0};
  6.     int prime[flag] = {0};

  7.     prime[0] = 2;
  8.     int i = 1;
  9.     int j = 2;
  10.     int k = 0;
  11.     bool yes = true;
  12.     int value = j;

  13.     while(true)
  14.     {
  15.         if(value > flag)
  16.         {
  17.             break;
  18.         }
  19.         k = 0;
  20.         while( k < i)
  21.         {
  22.             while(value % prime[k] == 0)
  23.             {
  24.                 temp[prime[k]-1] += 1;
  25.                 value /= prime[k];
  26.                 yes = false;
  27.             }
  28.             if(value > prime[k])
  29.             {
  30.                 k++;
  31.             }else
  32.             {
  33.                 break;
  34.             }
  35.         }
  36.         if(yes)
  37.         {
  38.             prime[i++] = value;
  39.             temp[value-1] = 1;
  40.         }

  41.         for(int my = 0; my < flag; my++)
  42.         {
  43.             if(array[my] < temp[my])
  44.             {
  45.                 array[my] = temp[my];
  46.             }
  47.             temp[my] = 0;
  48.         }

  49.         j += 1;
  50.         value = j;
  51.         yes = true;
  52.     }

  53.     for(j = 0; j < i; j++)
  54.     {
  55.         printf("%d\n",prime[j]);
  56.     }

  57.     printf("\n");
  58.     *answer = 1;
  59.     for(j = 0; j < flag; j++)
  60.     {
  61.         printf("%d\n", array[j]);
  62.         *answer *= (int) pow(j+1, array[j]);
  63.     }
  64. }

  65. int main(int argc, char *argv[])
  66. {
  67.     ElementType  ret;
  68.     getMinNumberOfFlag(&ret, 30);
  69.     printf("answer:%d\n",ret);
  70.     return 0;
  71. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-20 15:17:49 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2020-7-23 15:19 编辑

C++ 0ms
  1. #include<iostream>
  2. using namespace std;



  3. int main() {
  4.     ios::sync_with_stdio(false);

  5.     unsigned x, y, temp, i, result = 1;


  6.     for (i = 1; i <= 20; ++i) {
  7.         x = result;
  8.         y = i;

  9.         while (y) {
  10.             temp = x % y;
  11.             x = y;
  12.             y = temp;
  13.         }

  14.         result *= i / x;
  15.     }


  16.     cout << result << endl;
  17.     return 0;
  18. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-4-20 15:18:32 | 显示全部楼层
代号-K 发表于 2020-3-12 18:28
很多欧拉计划中解题方法都可以用质数来求解
感觉最简单的算法,速度应该是最快的
10: 2520

其实只要求1-20的最小公倍数就可以了……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-7 14:43:12 | 显示全部楼层
  1. def isOK(x):
  2.     for i in range(1, 21):
  3.         if x % i:
  4.             return False
  5.     else:
  6.         return True


  7. num = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19
  8. i = num
  9. while True:
  10.     if isOK(i):
  11.         break
  12.     i += num

  13. print(i)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-23 09:25:06 | 显示全部楼层
本帖最后由 xuan1788 于 2020-7-23 09:38 编辑
牡丹花下死做鬼 发表于 2015-7-19 21:57
不习惯用python 还是C写的没怎么优化 大概一秒不到点出的答案 232792560


感觉经典的最小公倍数辗除法和质数累加的原理由异曲同工之妙呀

辗除法:

  1. def f(a, b):
  2.     if a>b:
  3.         t = a
  4.         a = b
  5.         b = t

  6.     t = a
  7.     while t%a|t%b:
  8.         t += a
  9.     return t

  10. def main():
  11.     COUNT = 20
  12.     a = []
  13.     for i in range(0, COUNT):
  14.         a.append(i + 1)

  15.     k = 1

  16.     for i in range(0, COUNT):
  17.         k = f(k, a[i])

  18.     print("\n最小公倍数为:%d" % k)

  19. if __name__ == "__main__":
  20.     main()
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-23 11:57:43 | 显示全部楼层
xuan1788 发表于 2020-7-23 09:25
感觉经典的最小公倍数辗除法和质数累加的原理由异曲同工之妙呀

辗除法:

辗转相除法应该是这样的吧:
  1. def gcd(x: int, y: int) -> int:
  2.     while y:
  3.         x, y = y, x % y
  4.         
  5.     return x


  6. def lcm(x: int, y: int) -> int:
  7.     return x*y//gcd(x, y)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-23 13:29:02 | 显示全部楼层
永恒的蓝色梦想 发表于 2020-7-23 11:57
辗转相除法应该是这样的吧:

没错:
<while y:
x, y = y, x%y>

这种形式更符合辗除的字面意思,我的方法是从累加的角度得到辗除的结果,其实除法乘法在我看来,都可以用加减法做改写,当然,只是个人看法~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-23 13:33:09 | 显示全部楼层

然而效率太低了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-24 13:27:11 | 显示全部楼层
  1. a = 2520
  2. flag = 1
  3. while flag:
  4.     a += 20
  5.     for b in range(11,21):
  6.         if a % b != 0 :
  7.             break
  8.         if b == 20:
  9.             flag = 0
  10. print(a)
复制代码

emmm/最直白方法。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-30 20:49:51 | 显示全部楼层
  1. from time import time

  2. def beishu(x,y):
  3.     if x > y:
  4.         x,y = y,x
  5.     for i in range(1,x*y):
  6.         if y*i%x==0:
  7.             return y*i

  8. t1 = time()
  9. n = int(input('请输入需要求的数字:'))
  10. m = n
  11. w =1
  12. for i in range(1,m):
  13.     w = beishu(w,i+1)
  14.    
  15. print('%d 是最小的能被 1-%d 中每个数字整除的正整数' % (w,m))

  16. t2 = time()
  17. t=t2-t1
  18. print('耗时为:%s' % t)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 22:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表