Project Euler problem 21

来源:互联网 发布:php图书管理系统实例 编辑:程序博客网 时间:2024/06/14 08:08

求1到10000中满足某种条件的数的和


这个条件是。 假设该数为x,x除了本身的所有因子的和为y, y除了本身的所有因子的和为z 并且 x != y, z == x  则这一对x,y称为亲和数对  x, y都称为亲和的。

然后求1到1W中所有亲和数的和


我最初的想法就是对每个数求一下因子和。然后就出来了

注意求因子是sqrt(n)的

其实还能优化


注意 ,假设一个数可以表示成这样的东西

a = p1 ^ x1 * p2 ^ x2 * p3 ^ x3 * p4 ^ x4.........

其中p1, p2,p3....都是素因子

然后x1, x2,x3...都是非负数

那么这个数所有因子和可以表示为这样

sumofdivisors = (p1 ^ 0 + p1 ^ 1 + p1 ^ 2 .... + p1 ^ x1) * (p2 ^ 0 + p2 ^ 1 + p2 ^ 2 + ..... + p2 ^ x2) * ..........

这个东西应该比较好理解吧。

然后发现每个括号内都是等比数列

就变成了sumofdivisors = ((p1 ^ (x1 + 1) - 1) / (p1 - 1)) * ((p2 ^ (x2 + 1) - 1) / (p2 - 1)) * ......

然后我们求出这些x1, x2,....就能算出来了

这个应该比裸求快一些吧。


不过呢。

还有更快的写法。

类似于筛法求素数的那种写法

看代码,很容易理解

下面是求[A, B]区间内所有亲和数的和的代码


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <set>#include <stack>#include <cmath>#include <map>#include <ctime>#define MAXN 111111#define INF 100000007using namespace std;int A, B;int a[222222];int ans[111];int cnt;int main(){    scanf("%d%d", &A, &B);    for(int i = 1; i <= B; i++)        for(int j = i + i; j <= B; j += i)            a[j] += i;    for(int i = A; i <= B; i++)        if(a[i] > i && a[i] <= B && i == a[a[i]])            ans[cnt++] = i;    int sum = 0;    for(int i = 0; i < cnt; i++)        sum += ans[i], sum += a[ans[i]];    printf("%d\n", sum);    return 0;}


原创粉丝点击