欧拉计划 第二十三题

A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.

A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.

As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.

Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers. !

完美数字是一个数字,其正确除数的总和恰好等于数字。例如,28的适当除数之和为1 + 2 + 4 + 7 + 14 = 28,这意味着28是一个完美数。

如果n的适当除数之和小于n,则n被称为不足,如果该和超过n则称为n。

由于12是最小的有限数,1 + 2 + 3 + 4 + 6 = 16,可以写成两个有限数之和的最小数是24.通过数学分析,可以看出所有整数都大于28123可以写成两个数字的总和。然而,即使已知不能表示为两个充裕数的总和的最大数小于该限制,也不能通过分析进一步减小该上限。

找到所有正整数的总和,这些正整数不能写为两个数字的总和。

思路

1.一个正整数n被分解成质数相乘,如12 = 2(2)*3; p1(a1) p2(a2)p3(a3);

2.因子个数=(a1+1)(a2+1)(a3+1),如12的因子个数=(2+1)(1+1)=6;

3.F(A * B)=F(A)*F(B);

4.因子和:Eg 12因子和=28=(1+3)(1+2 + 2*2)

Sum_factor(n) = (p1^0 + p1^1 + p1 ^2 + ... + p1^a1)*(P2^0 + p2^1 +...+p2^a2) *... *(pn^0 + pn ^1 +...+ pn^an)

= 求乘[1-pi^(ai + 1)]/1-pi;

F(B) = F(A)/{[1-p1^ (a1+1)]/1-p1}*{[1-p1^(a1+2)]/1-p1}=F(A) * [1 - p1^(a1+2)]/[1 - p1^(a1+1)];

#include <stdio.h>

#define max 28123

int prime[max + 5] = {0};
int isprime[max + 5] = {0};
int Sum_factor[max + 5] = {0};
int num[max + 5] = {0};

int main(){
	Sum_factor[1] = 0;
	for(int i = 2; i <= max; i++){//Sum_factor存放的是各个因子和;
		if(!isprime[i]){
			isprime[i] = i;
			prime[++prime[0]] = i;
			Sum_factor[i] = i + 1;
		}
		for(int j = 1; j <= prime[0]; j++){
			if(i * prime[j] > max) break;
			if(i % prime[j] == 0){
				isprime[i * prime[j]] = isprime[i] * prime[j];
				Sum_factor[i * prime[j]] = Sum_factor[i] * (isprime[i] * prime[j] * prime[j] - 1) / (isprime[i] * prime[j] - 1);
				break;
			}else{
				isprime[i * prime[j]] = prime[j];
				Sum_factor[i * prime[j]] = Sum_factor[i] * Sum_factor[prime[j]];
			}
		}
	}
	Sum_factor[0] = 0;//Sum_factor[0]存放的是充裕数的个数;
	for(int i = 0; i <= max; i++){
		Sum_factor[i] -= i;
		if(Sum_factor[i] > i) Sum_factor[++Sum_factor[0]] = i;//Sum_factor[i]中存放的是第i个数是充裕数;与之前的线性筛一样;
	}
	for(int i = 1; i <= Sum_factor[0]; i++){
		for(int j = i; j <= Sum_factor[0]; j++){
			if(Sum_factor[i] + Sum_factor[j] > max) break;
			num[Sum_factor[i] + Sum_factor[j]] = 1;//把能使两个充裕数求和的数标记为1;
		}
	}
	int sum = 0;
	for(int i = 0; i <= max; i++){
		if(!num[i]) sum += i;//未被标记的数就可以累加起来啦;
	}
	printf("%d\n", sum);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38362049/article/details/81026831