Project Euler problem 21

求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 100000007
using 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值