21
我们需要实现线性筛因数和 \(\sigma(n)\),这一点是可以办到的。
由算数基本定理可知:\(n = p_1^{\alpha_1}p_2^{\alpha_2}\ldots p_k^{\alpha_k}\),而 \(\sigma(n) = (1 + p_1 + \cdots + p_1^{\alpha_1})\ldots(1 + p_k + \cdots + p_k^{\alpha_k})\)。
设 \(p[i]\) 表示 \(i\) 中最小质因子的等比数列和,\(d[i]\) 表示 \(\sigma(i)\),则由线性筛的性质可知:
-
\(isprime(i) = 1\),则 \(p[i] = d[i] = i + 1\) 显然。
-
\(i \bmod primes[j] \neq 0\),则该质数之前从未出现过,由于我们从小到大枚举质数,所以可以做如下更新:
\[\begin{aligned}&d[i * primes[j]] = d[primes[j]] * d[i] + 1 \\ &p[i * primes[j]] = primes[j] + 1\end{aligned}
\]
- \(i \bmod primes[j] = 0\),该质数以前出现过,所以我们做如下更新:
\[\begin{aligned}&d[i * primes[j]] = d[i] / p[i] * (p[i] * primes[j] + 1) \\ &p[i * primes[j]] = p[i] * primes[j] + 1 \end{aligned}
\]
注意顺序,结果判断 \(d[d[i]] = i\) 且 \(i \neq d[i]\) 即可。
// cpp
#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int st[N], primes[N], d[N], p[N], cnt;int main() {d[1] = 1;for (int i = 2; i < N; i ++ ) {if (!st[i]) p[i] = d[i] = i + 1, primes[cnt ++ ] = i;for (int j = 0; i * primes[j] < N; j ++ ) {st[i * primes[j]] = 1;if (i % primes[j] == 0) {d[i * primes[j]] = d[i] / p[i] * (p[i] * primes[j] + 1);p[i * primes[j]] = p[i] * primes[j] + 1;break;}d[i * primes[j]] = d[i] * d[primes[j]];p[i * primes[j]] = primes[j] + 1;}}for (int i = 1; i < N; i ++ ) d[i] -= i;int n = 10000, ans = 0;for (int i = 1; i <= n; i ++ ) {if (d[i] != i && i == d[d[i]]) {ans += i;}}cout << ans;return 0;
}