LOJ #2234. 「JLOI2014」聪明的燕姿(搜索 + 数论)

题意

给出一个数 S ,输出所有约数和等于 S 的数。

S2×109 ,数据组数 100

题解

首先用约数和定理:

(1)n=ipiai(2)σ(n)=i(j=0aipij)

那么,我们可以通过从小到大来枚举质数 pi 及其指数 ai 来搜索。

  • 若当前需要得到的 S 可以表示为一个未搜索过的质数与 1 的和,那么之前的数与这个质数的乘积是一个合法答案。

  • 对于每一个使得 (p+1)×(p+1)<Sp ,枚举可能的 ai ,递归。

    因为在第一种情况会把 ai=1 的特判掉(这种数出现并且仅出现一次),然后剩下的 ai2 ,所以至少为 1+p+p2

最后当一直除到 1 的时候就是答案了qwq

最开始随便用筛法筛素数就行了,复杂度 O(pass) 。。。

总结

对于约数和之类的题,考虑对于 ai=1ai2 的情况分别考虑就行了,前者只存在一个,后者 p

代码

随便看看实现就行了。。跑的速度还行qwq

#include <bits/stdc++.h> #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i) #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i) #define Set(a, v) memset(a, v, sizeof(a)) #define Cpy(a, b) memcpy(a, b, sizeof(a)) #define debug(x) cout << #x << ": " << (x) << endl #define DEBUG(...) fprintf(stderr, __VA_ARGS__) #define mp make_pair using namespace std; template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;} template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;} inline int read() { int x(0), sgn(1); char ch(getchar()); for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1; for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48); return x * sgn; } void File() { #ifdef zjp_shadow freopen ("2234.in", "r", stdin); freopen ("2234.out", "w", stdout); #endif } set<int> S; const int Maxn = sqrt(2e9); bitset<Maxn + 5> is_prime; void Math_Init(int maxn) { is_prime.set(); is_prime[0] = is_prime[1] = false; For (i, 2, maxn) if (is_prime[i]) for (int j = i * 2; j <= maxn; j += i) is_prime[j] = false; } inline bool Judge(int x) { if (x <= Maxn) return is_prime[x]; for (int i = 2; i * i <= x; ++ i) if (!(x % i)) return false; return true; } void Dfs(int x, int cur, int pre) { if (x == 1) { S.insert(cur); return ; } if (x - 1 > pre && Judge(x - 1)) S.insert(cur * (x - 1)); For (p, pre + 1, sqrt(x + .5)) if (is_prime[p]) { int sum = p + 1, here = p; while (sum <= x) { if (!(x % sum)) Dfs(x / sum, cur * here, p); here *= p; sum += here; } } } int main () { File(); Math_Init(Maxn); int x; while (~scanf("%d", &x)) { S.clear(); Dfs(x, 1, 1); printf ("%d\n", (int)S.size()); for (int cur : S) printf ("%d ", cur); if ((bool)S.size()) putchar ('\n'); } return 0; }

__EOF__

本文作者zjp_shadow
本文链接https://www.cnblogs.com/zjp-shadow/p/9761316.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zjp_shadow  阅读(460)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示