洛谷 P4397 [JLOI2014]聪明的燕姿 / TOPOI 测验1315, 问题E: 1935: 聪明的燕姿 解题报告
题目链接 :
1. 洛谷
2.topoi
、
大致题意:输入一个数s,找出所有约数和为s的数
关于一个数的约数和求法:
一个>1的整数可以被分解为多个 质数 的乘方,设数 s = p1k1 * p2k2 * p3k3 *......*pnkn
根据 组合 的思想 s的约数和 = (p10 +p11+p12+......+p1k1)*(p20 +p21+p22+......+p2k2)*........*(pn0 +pn1+pn2+......+pnkn);
数据很大,有多组测试数据,首先想到预处理
预处理 2 * 10^9内的所有质数?(神仙也没法阻止你TLE)
事实上只要处理√2*10^9内的质数行了。Why? 注:√2*10^9 ≈ 50000
设输入的数为s,有一个质数 k>√s, 在分解s的过程中,k最多只能取1个
所以在找答案的过程中,只要判断当前分解的数 a = k + 1(k+k0=k+1)就可以加入答案
但在实际搜索的过程中,假设当前在枚举第 x 个质数,分解的数为 a,当a - 1 > t[x] 且 (a - 1)是质数时,就可以加入答案。
因为如果(a-1)是质数,之后枚举的所有质数 p,一定满足 p * p <= a (前面已经提到只枚举 < √a 的质数),所以 p ≠ a-1,不会造成答案重复
预处理质数 :
范围虽然开了根号,但用普通筛选肯定不行,(估计TOPOI又要炸了)
这里要用到线性筛来预处理
线性筛主体思想:让每一个数只筛选出部分合数,其余的让别的数来筛,时间复杂度 O(n)
实现:
for (register int i = 2; i <= maxn; i++) {
if (!ok[i]) t[++num] = i;
for (register int j = 1; j <= num; j++) {
if (t[j] * i > maxn) break;
ok[t[j] * i] = 1;
if (i % t[j] == 0) break;
}
} //线性筛 预处理 maxn 内的质数
处理出质数后,就可以开始暴力枚举
搜索的时候 从n除到1或从1乘到n都可以 (因为运算符不同, 从n除到1貌似更快一些)
这里附上 2 种做法的代码(差不多)
(代码跟 洛谷里的题解 差不多,毕竟我也是看了题解)
细节看一下代码中的注释吧 (代码巨丑)
代码1:
#include <bits/stdc++.h>
using namespace std;
#define maxn 50000
int n, num, ans[maxn * 2], t[maxn + 10], tot; //ans存答案,t存质数,tot记录答案数
bool ok[maxn + 10]; //ok表示是否是质数
bool check (int x) {
if (x <= maxn) return !ok[x]; //优化 :若这个数已经预处理过,就不用重复做了
for (register int i = 1; t[i] * t[i] <= x; i++) if (x % t[i] == 0) return false;
//这里判断质数只要用前面 质数 来判断就行了,节省时间
return true;
}
void dfs (int x, int sum, int now) {
if (sum == 1) {ans[++tot] = now; return;} //当分解到 1 时说明方案成立,加入答案
if (sum > t[x] + 1 and check (sum - 1)) ans[++tot] = now * (sum - 1); //特判是否满足上述情况
for (register int k = x + 1; t[k] * t[k] <= sum; k++) //外重枚举质数
for (register int ss = 1 + t[k], sn = t[k]; ss <= sum; sn *= t[k], ss += sn) {//内重枚举个数
if (sum % ss != 0) continue; //剪枝 :如果除不尽就别做了
dfs (k, sum / ss, now * sn);
}
}
int main() {
for (register int i = 2; i <= maxn; i++) {
if (!ok[i]) t[++num] = i;
for (register int j = 1; j <= num; j++) {
if (t[j] * i > maxn) break;
ok[t[j] * i] = 1;
if (i % t[j] == 0) break;
}
} //线性筛 预处理 maxn 内的质数
while (~scanf ("%d", &n)) { //~scanf实现多组数据读入
tot = 0;
dfs (0, n, 1);
sort (ans + 1, ans + tot + 1);
printf ("%d\n", tot);
for (register int i = 1; i <= tot; i++) printf ("%d ", ans[i]);
if (tot) puts ("");
}
return 0;
}
代码2:
#include <bits/stdc++.h>
using namespace std;
#define maxn 50000
int n, num, ans[maxn * 2], t[maxn + 10], tot; //ans存答案,t存质数,tot记录答案数
bool ok[maxn + 10]; //ok表示是否是质数
bool check (int x) {
if (x <= maxn) return !ok[x]; //优化 :若这个数已经预处理过,就不用重复做了
for (register int i = 1; t[i] * t[i] <= x; i++) if (x % t[i] == 0) return false;
//这里判断质数只要用前面 质数 来判断就行了,节省时间
return true;
}
void dfs (int x, int sum, int now) {
if (sum == n) {ans[++tot] = now; return;} //当乘积到 n 时说明方案成立,加入答案
if (n / sum > t[x] + 1 and check (n / sum - 1)) ans[++tot] = now * (n / sum - 1); //特判是否满足上述情况
for (register int k = x + 1; t[k] * t[k] <= n / sum; k++) //外重枚举质数
for (register int ss = 1 + t[k], sn = t[k]; ss <= n / sum; sn *= t[k], ss += sn) { //内重枚举个数
if ((n / sum) % ss != 0) continue; //剪枝 :如果除不尽就别做了
dfs (k, sum * ss, now * sn);
}
}
int main() {
for (register int i = 2; i <= maxn; i++) {
if (!ok[i]) t[++num] = i;
for (register int j = 1; j <= num; j++) {
if (t[j] * i > maxn) break;
ok[t[j] * i] = 1;
if (i % t[j] == 0) break;
}
} //线性筛 预处理 maxn 内的质数
while (~scanf ("%d", &n)) { //~scanf实现多组数据读入
tot = 0;
dfs (0, 1, 1);
sort (ans + 1, ans + tot + 1);
printf ("%d\n", tot);
for (register int i = 1; i <= tot; i++) printf ("%d ", ans[i]);
if (tot) puts ("");
}
return 0;
}
点一下左边的推荐吧!谢谢~~~
洛谷 P4397 [JLOI2014]聪明的燕姿 / TOPOI 测验1315, 问题E: 1935: 聪明的燕姿 解题报告的更多相关文章
- 洛谷P4397 [JLOI2014]聪明的燕姿
传送门 dfs的时候莫名其妙深度太大过不了……然后死活找不出哪里错…… 首先,约数和这东西是个积性函数,或者直接点的话就是如果$$n=p_1^{a_1}p_2^{a_2}p_3^{a_3}…p_m^{ ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 洛谷P3258 [JLOI2014]松鼠的新家
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 题解
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)
题目描述松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前来 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家
树剖,裸题,鉴定完毕. 我是题面 读完题,恩,树剖,裸题,没劲. 处理很简单,既然每到一个房间吃一块糖,那么就在每条路径上的每个房间放一颗糖,但是每条路径的终点也就是下一条路径的起点,在这里只能加一次 ...
- 洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...
- 洛谷 3285 [JLOI2014]松鼠的新家
[题解] 给出一条路径,问树上的点被经过了几次. 显然树剖之后树上差分就好了. #include<cstdio> #include<algorithm> #define N 3 ...
随机推荐
- FFMPEG内存操作(二)从内存中读取数及数据格式的转换
相关博客列表: FFMPEG内存操作(一) avio_reading.c 回调读取数据到内存解析 FFMPEG内存操作(二)从内存中读取数及数据格式的转换 FFmpeg内存操作(三)内存转码器 在雷神 ...
- 【转】 Pro Android学习笔记(七九):服务(4):远程服务的实现
目录(?)[-] 远程服务的实现小例子 对外开放远程服务的接口 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flow ...
- java web基础学习 Forward和Redirect区别
Forward和Redirect代表了两种请求转发方式:直接转发和间接转发.对应到代码里,分别是RequestDispatcher类的forward()方法和HttpServletRequest类的s ...
- java基础知识(10)---包
包:定义包用package关键字. 1:对类文件进行分类管理. 2:给类文件提供多层名称空间. 如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中 ...
- RubyGems 镜像 - 淘宝网
为什么有这个? 由于国内网络原因(你懂的),导致 rubygems.org 存放在 Amazon S3 上面的资源文件间歇性连接失败.所以你会与遇到 gem install rack 或 bundle ...
- 每天一道算法题(4)——O(1)时间内删除链表节点
1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...
- shell解决DOS攻击生产案例
解决DOS攻击生产案例企业实战题5:请用至少两种方法实现!写一个脚本解决DOS攻击生产案例.提示:根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100,即调用防火墙命令封 ...
- 具体问题:Spring 事务的隔离性,并说说每个隔离性的区别
使用步骤: 步骤一.在spring配置文件中引入<tx:>命名空间<beans xmlns="http://www.springframework.org/schema/b ...
- win7 32位安装 python 及Numpy、scipy、matplotlib函数包
操作系统: win7 64位,但选择安装32位的python. 1,python下载安装 https://www.python.org/downloads/ 下载2.7版,一路下一步安装. 并在pat ...
- Multi-task Pose-Invariant Face Recognition 论文笔记
摘要: 在不受限制的环境中拍摄的人脸图像通常包含显著的姿态变化,这会显著降低设计用于识别正面的算法的性能.本文提出了一种新颖的面部识别框架,能够处理±90°偏航范围内的全方位姿势变化.所提出的框架首先 ...