[JLOI2014]聪明的燕姿
题目链接
题解链接
题目
城市中人们总是拿着号码牌,不停寻找,不断匹配,可是谁也不知道自己等的那个人是谁。
可是燕姿不一样,燕姿知道自己等的人是谁,因为燕姿数学学得好!燕姿发现了一个神奇的算法:假设自己的号码牌上写着数字 S,那么自己等的人手上的号码牌数字的所有正约数之和必定等于 S。
所以燕姿总是拿着号码牌在地铁和人海找数字(喂!这样真的靠谱吗)可是她忙着唱《绿光》,想拜托你写一个程序能够快速地找到所有自己等的人。
分析
这题其实很简单,其实就是个数论题 + 搜索题。
启发我们原来数论可以用暴搜解决。
代码 :
#include <bits/stdc++.h>
using namespace std;
int vis[100005], pri[100005], cnt, tot, ans[100005];
void shai() {
for(int i = 2; i <= 100000; ++i) {
if(vis[i] == 0) vis[i] = i, pri[++tot] = i;
for(int j = 1; j <= tot; ++j) {
if(i * pri[j] > 100000 || pri[j] > vis[i]) break;
vis[i * pri[j]] = pri[j];
}
}
}
inline bool pan(int x) {
if(x == 1) return 0;
for(int i = 2; i * i <= x; ++i)
if(x % i == 0) return 0;
return 1;
}
void dfs(int now, int x, int s) {
if(now == 1) return ans[++cnt] = s, void();
if(pan(now - 1) && now > pri[x]) ans[++cnt] = s * (now-1);
for(int i = x; pri[i] * pri[i] <= now; ++i) {
int t = pri[i], sum = pri[i] + 1;
for(; sum <= now; t *= pri[i], sum += t)
if(now % sum == 0) dfs(now/sum, i + 1, s * t);
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
shai(); int n;
while(cin >> n) {
cnt = 0, dfs(n, 1, 1);
sort(ans + 1, ans + cnt + 1);
cout << cnt << '
';
for(int i = 1; i <= cnt; ++i) cout << ans[i] << ' ';
if(cnt) co ut << '
';
}
return 0;
}