鱼C论坛

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

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

[复制链接]
发表于 2018-10-14 21:15:10 | 显示全部楼层
#第5题
#2520 是最小的能被 1-10 中每个数字整除的正整数。
#最小的能被 1-20 中每个数整除的正整数是多少?
#第一步求范围类的所有素数
import math
a=int(input('请输入一个正整数:'))
c=[]
for i in range(2,a+1):
    a1=0
    for each in range(2,i-1):      
        if i%each==0:
            a1=1
            break
    if a1==0:
        #print(i)
        c.append(i)
#第二步,求范围类有没有这些素数的倍数并装到字典中去
dic={}
for i2 in c:
    for i1 in range(1,a):   
        if i1%i2==0 and i1!=i2:
            dic[i2]=i1
#将字典中素数最大的倍数写进列表
list1=list(dic.values())
#用list1中每个数除以c的前位数相同的数求出kn
kn=[]
for xxoo in range(len(list1)):
    kn.append(int(math.log(list1[xxoo],c[xxoo])))
#最后计算结果
result=1
for ooxx in range(len(kn)):
    result*=c[ooxx]**kn[ooxx]
for oxox in range(len(kn),len(c)):
    result*=c[oxox]
print('{}是最小的能被 1-{}中每个数字整除的正整数。'.format(result,a))
终于完成了,代码很简单,就是讲公式分解之后一步步写回去的,优点就是计算速度还是相当快的!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-11-21 18:16:49 | 显示全部楼层
import time
print('开始计算')
start_time = time.time()
t = True
n = 20 
while t:
        count = 0 # 记录20个数字是否都能整除,如果count=20,就说明能整除
        for i in range(1,21):
                if n % i == 0:
                        count += 1
                if count == 20:
                        result = n
                        t = False # 一算出结果就跳出while,即为最小
                        break

        n += 1   # n += 1 ,对最后结果没有影响,结果已经用result替代
print('最后结果为%s'%str(result))
end_time = time.time()
print('耗时:%s'%str(end_time - start_time))

笨方法算
下面是结果:
开始计算
最后结果为232792560
耗时:1748.6437139511108
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 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 | 显示全部楼层
import time as t
start = t.perf_counter()
i = j = 11*13*17*19
list1 = [12,14,15,16,18,20]
s = 1
while s:
    for each in list1:
        if i % each != 0:
            i += j
            s = 1
            break
        else:
            s = 0
end = t.perf_counter()
print(i)
print(end - start)
232792560
0.0015221600000000016
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

Python
from math import gcd
res = i = 1

while i <= 20:
    res *= i // gcd(res, i)
    i += 1

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

使用道具 举报

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

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

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

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
typedef long long ElementType;
void getMinNumberOfFlag( ElementType *answer, int flag)
{
    int array[flag] = {0};
    int temp[flag] = {0};
    int prime[flag] = {0};

    prime[0] = 2;
    int i = 1;
    int j = 2;
    int k = 0;
    bool yes = true;
    int value = j;

    while(true)
    {
        if(value > flag)
        {
            break;
        }
        k = 0;
        while( k < i)
        {
            while(value % prime[k] == 0)
            {
                temp[prime[k]-1] += 1;
                value /= prime[k];
                yes = false;
            }
            if(value > prime[k])
            {
                k++;
            }else
            {
                break;
            }
        }
        if(yes)
        {
            prime[i++] = value;
            temp[value-1] = 1;
        }

        for(int my = 0; my < flag; my++)
        {
            if(array[my] < temp[my])
            {
                array[my] = temp[my];
            }
            temp[my] = 0;
        }

        j += 1;
        value = j;
        yes = true;
    }

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

    printf("\n");
    *answer = 1;
    for(j = 0; j < flag; j++)
    {
        printf("%d\n", array[j]);
        *answer *= (int) pow(j+1, array[j]);
    }
}

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

使用道具 举报

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

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



int main() {
    ios::sync_with_stdio(false);

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


    for (i = 1; i <= 20; ++i) {
        x = result;
        y = i;

        while (y) {
            temp = x % y;
            x = y;
            y = temp;
        }

        result *= i / x;
    }


    cout << result << endl;
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> 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 | 显示全部楼层
def isOK(x):
    for i in range(1, 21):
        if x % i:
            return False
    else:
        return True


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

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

使用道具 举报

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


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

辗除法:
def f(a, b):
    if a>b:
        t = a
        a = b
        b = t

    t = a
    while t%a|t%b:
        t += a
    return t

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

    k = 1

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

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

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

使用道具 举报

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

辗除法:

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


def lcm(x: int, y: int) -> int:
    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
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-6-10 11:56

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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