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