euler五十讲(一)

今天在一个网站上刷题,这个网站很有趣。

在这里插入图片描述
https://projecteuler.net

这个网站是纯英文网站,需要注册,登陆。

接下来,博主开启欧拉五十讲的刷题之旅啦。

Problem 1:Multiples of 3 and 5

If we list all the natural numbers below 10 that are multiples of 3 or
5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.

问题描述

如果我们列出所有低于10的自然数,它们是3或5的倍数,则得到3、5、6和9。这些倍数的总和为23。

找出1000以下3或5的所有倍数的总和。

初级代码

从1到999遍历,满足条件的数字加入输出和中。

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int main()
{
	int sum =0;
	for(int i=1;i<1000;i++)
		if(i%3==0 || i%5==0)
			sum += i;
	cout<<sum;
	return 0;
}

改进代码

等差数列的思路,大大减少运算次数,降低时间复杂度。
求出1-999中所有3的倍数,5的倍数,15的倍数。

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int main()
{
	int sum,sum1,sum2,sum3;
	sum1 = (3+999)*333/2;//1-999中所有被3整除的数字
	sum2 = (5+995)*199/2;//1-999中所有被5整除的数字
	sum3 = (15+990)*66/2;//1-999中所有被15整除的数字
	sum = sum1 + sum2 - sum3;
	cout<<sum;
	return 0;
}

回答:233168

Problem 2:Even Fibonacci numbers

Each new term in the Fibonacci sequence is generated by adding the
previous two terms. By starting with 1 and 2, the first 10 terms will
be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …

By considering the terms in the Fibonacci sequence whose values do not
exceed four million, find the sum of the even-valued terms.

问题描述

斐波那契数列中的每个新项都是通过将前两个项相加而生成的。从1和2开始,前10个术语将是:

1,2,3,5,8,13,21,34,55,89,…

通过考虑斐波那契数列中值不超过四百万的项,找到偶值项的总和。

初级代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
int32_t Fibula[50];
int main()
{
	Fibula[1] = 1;Fibula[2] = 2;
	int64_t sum = Fibula[2];
	for(int i=3;i<=50;i++){
		Fibula[i] = Fibula[i-1] + Fibula[i-2];
		if(Fibula[i] >4000000)//判断跳出循环
			break;
		if(Fibula[i] % 2 == 0)
			sum += Fibula[i];//求和
	}
	cout<<sum<<endl;
	return 0;
}

回答:4613732

Problem 3:Largest prime factor

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

问题描述

13195的素因子是5、7、13和29。

什么是600851475143的最大素因子?

代码

任意一个合数m,都可以表示成 m=a*b的形式,而且必有a<=sqrt(m)<=b的形式。

这里给出一种暴力求解的方法,但不具有普适性。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
#define NUM 600851475143
#define sqrtNUM 800000
int8_t mark[800001];
int main()
{
	int64_t num = NUM;
	int64_t max_prime;
	//素数筛
	memset(mark,1,sizeof(mark));
	mark[0] = mark[1] = 0;
	for(int c=2; c*c<sqrtNUM; c++){
		if(mark[c] == 1){
			for(int i=2;c*i<sqrtNUM;i++)
				mark[c*i] = 0;
		}
	}
	int32_t i;
	for(i=sqrtNUM;i>1;i--){
		if(mark[i] && num%i == 0)
			break;
	}
	if(i>1)
		cout<<i<<endl;
	return 0;
}

改进代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
#define NUM 600851475143
int main()
{
	int64_t num = NUM;
	int64_t max_prime;
	for(int64_t i=2;i*i<=num;i++){
		while(num%i==0){//进入循环的i一定是素数 因为如果不是素数,i=a*b,a,b<i,从而a,b也可以满足条件进入循环,显然矛盾
			num = num/i;
			max_prime = i;
		}
	}
	if(num != 1)
		max_prime = num;
		cout<<max_prime<<endl;
	return 0;
}

回答:6857

Problem 4:Largest palindrome product

A palindromic number reads the same both ways. The largest palindrome
made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit
numbers.

问题描述

回文数在两个方向上都相同。由两个两位数的乘积构成的最大回文数为9009 = 91×99。

查找由两个3位数字的乘积组成的最大回文数。

初级代码

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
//判断一个数是否为回文数
bool huiwen(int n)
{
	int m = n;
	int b = 0;
	int temp;
	while(m!=0){
		b = b*10;
		temp = m%10;
		b = b+temp;
		m = m/10;
	}
	if(b == n)
		return true;
	else
		return false;
}
int main()
{
	int32_t max = 999*999;//max = 998001;
	int32_t min = 100*100;//min = 10000;
	int maxnum=0,num;
	for(int i=999;i>=100;i--)
	for(int j=999;j>=100;j--){
		if(huiwen(i*j)){
			num = i*j;
			if(maxnum < num)
				maxnum = num;//更新最大回文数
		}
	}
	cout<<maxnum;
	return 0;
}

回答:906609

Problem 6:Sum square difference

The sum of the squares of the first ten natural numbers is,
12+22+…+102=385
The square of the sum of the first ten natural numbers is,
(1+2+…+10)2=552=3025
Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is
3025−385=2640
Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.

问题描述

前十个自然数的平方和是385
前十个自然数之和的平方为3025
因此,前十个自然数的平方之和并将该和的平方之间的差为3025-385=2640。

求出前一百个自然数的平方和与和的平方之差。

代码

大家都知道高斯的1+2+3+…+100=5050
这便是1到100的自然数之和。 一般的自然数求和,我们可以用下面的公式: Sn = n * (n + 1) / 2
在这里插入图片描述

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
int main()
{
	int32_t sum1,sum2;
	sum1 = (1+100)*100/2;
	sum1 = sum1*sum1;//1-100和的平方
	sum2 = 100*(100+1)*(2*100+1)/6;//1-100平方的和
	cout<<sum1-sum2;
	return 0;
}

回答:25164150

Problem 28:Number spiral diagonals

在这里插入图片描述

问题描述

在这里插入图片描述

代码

这里说一下思路:
观察这个由所有对角线元素组成的数列:

1357913172125...

其中1是最里面一层的对角线元素,3,5,7,9是第二层的对角线元素,13,17,21,25是第三层的对角线元素。
从1到(3,5,7,9),增量add为2
从(3,5,7,9)到(13,17,21,25),增量为4

所以,我们可以把这个数列完全构造出来再求和

1357913172125313743495765738191101111121...

还有一个问题要解决,10011001大小的矩阵的对角线元素一共有多少层呢?可以递推一下。

第一层一共有1个数 12
第二层一共有9个数 32
第三层一共有25个数 52

所以第i层一共有(2
i-1)2个数
由此可以知道10011001的矩阵一共有10011001个数,对应的层数为2*i-1=1001,解得i=501

#include<iostream>
using namespace std;
int main()
{
	int64_t sum =1;//最后的总和
	int64_t i=1;//i表示对角线上的数
	int32_t ceng = 1;//螺旋层数
	//第i层需要(2*i-1)^2个数,如形成3层螺旋,需要25个数,也即是5*5
	//那么形成1001*1001,需要多少个数呢?
	//2*i-1 = 1001 ,i=501,螺旋层数最大为501,ceng<=501
	int32_t add = 2;//这个数列的增量
	for(ceng=2;ceng<=501;ceng++){
		for(int j=1;j<=4;j++){
			i += add;
			sum += i;
		}
		add += 2;//每多一层,add+2
	}
	cout<<sum;
	return 0;
}

改进代码

改进一下,对每一层先求和,构造出一个数列

第一层对角线元素为1, 和为1
第二层对角线元素为3,5,7,9,和为24
第三层对角线元素为13,17,21,25,和为76
第四层对角线元素为31,37,43,49,和为160

所以第n层的对角线元素之和为 4i2 -6i+6,其中i = 2*n-1

改进的代码如下:

int main()
{
	int64_t sum =1;//最后的总和,第一层为1
	int64_t temp=1;//i表示对角线上的数
	int32_t ceng = 1;//螺旋层数
	for(ceng=2;ceng<=501;ceng++){
		int i = 2*ceng - 1;
		temp = 4*i*i-6*i+6;
		sum += temp;
	}
	cout<<sum;
	return 0;
}

回答:669171001

Problem 30:Digit fifth powers

在这里插入图片描述

问题描述

在这里插入图片描述

代码

这是一个估算上界的题目,每位数的5次方最大为95约等于6*104
那么对于某个m位数:
大致有 10m === m * 6 * 104
那么 估计m最大也只能是6.

再粗略估计一下下限,m最小为4

所以满足条件的数只可能是4位数,5位数,或者6位数

#include<iostream>
using namespace std;
//求某个数n的5次幂
//注意0的n次方
//当n大于0时,等于0;
//当n等于0时,0的0次方没有意义;
//当n小于0时,也没有意义。
int getfifthpow(int n)
{
	return n*n*n*n*n;
}
//判断这个数是否为满足题目条件的特殊数字
bool issurprisenumber(int n)
{
	int32_t num = 0;
	int temp;
	int m = n;
	while(m!=0){
		temp = m%10;
		num += getfifthpow(temp);
		m = m/10;
	}
	return n == num;
}
int main()
{
	//只可能是4位数,5位数,或者6位数
	//暴力求解
	int32_t sum =0;
	for(int i=1000;i<=999999;i++)
		if(issurprisenumber(i)){
			sum += i;
			//cout<<i<<endl;
		}
	cout<<sum;
	return 0;
}

回答:443839

Problem 34:Digit factorials

145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145.

Find the sum of all numbers which are equal to the sum of the factorial of their digits.

Note: as 1! = 1 and 2! = 2 are not sums they are not included.

问题描述

145是一个奇特的数,等于1!+ 4!+ 5!= 1 + 24 + 120 = 145。
查找所有数字的总和,这些数字等于其数字的阶乘之和。
注意:为1!= 1和2!= 2不是总和,不包括在内。

代码

简单枚举算法

i从3开始循环,检查是否符合条件的数。

粗略估算上界

9! = 362880

设最大的数有m位,则10m <= m * 9! = m * 3.6*105

所以估计m最大为6

求解代码
#include<iostream>
using namespace std;
//求0-9的阶乘
int fact(int n)
{
	int ret = 1;
	if(n==0 || n==1)
		return ret;
	for(int i=2;i<=n;i++)
		ret *= i;
	return ret;
}
//判断是否是符合条件的数
bool iscuriousnumber(int n)
{
	int sum = 0;
	int m = n;
	while(m!=0){
		sum += fact(m%10);
		m = m/10;
	}
	return sum == n;
}
int main()
{
	int32_t i=3;
	int64_t ans = 0;
	//i最大为6位数
	for(i=3;i<999999;i++)
		if(iscuriousnumber(i)){
			cout<<i<<endl;
			ans += i;
		}
	cout<<ans;
	return 0;
}

输出这样的数有:
145
40585
sum = 145 + 40585 = 40730

回答:40730

Problem 36:Double-base palindromes

在这里插入图片描述

问题描述

十进制数585 = (1001001001)(二进制表示)

因此它在这两种进制下都是回文数。

找出所有小于106,并且在十进制和二进制下均回文的数,并求其的和。

(请注意,无论在何进制下,回文数均不考虑前导零。)

代码

上界为106,写一个函数来判断一个整数n在j进制下是否为回文数

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
#define MAXNUM 1000000
//判断数字n在j进制下是否为回文数
bool ishuiwen(int n,int j)
{
	int num=0;
	int m = n, temp;
	while(m){
		num *= j;
		temp = m%j;
		num += temp;
		m = m/j;
	}
	return num == n;
}
int main()
{
	int ans = 0;
	for(int i=1;i<MAXNUM;i++)
		if(ishuiwen(i,2) && ishuiwen(i,10)){
			//cout<<i<<endl;
			ans += i;
		}
	cout<<ans;
	return 0;
}
满足条件的数十进制表示如下:
1
3
5
7
9
33
99
313
585
717
7447
9009
15351
32223
39993
53235
53835
73737
585585

ans = 872187

回答:872187

发布了97 篇原创文章 · 获赞 101 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/practical_sharp/article/details/103916795