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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章