题目地址:http://codevs.cn/problem/1032/

分析:

题目数据有错。这题过不了才正常。

我调了非常久可是就是有两个点过不去。于是我把数据下了下来,找到WA的第五个点和第七个点。

题目描写叙述中,保证L<=U。但其实。数据5中,L>R。按我的写法是出不了解的,于是我特判这样的情况,在计算的时候把L和R对调。依旧过不了这个点。

而第七个点,输入数据为 999999999 1000000000,我用暴力跑了一遍,答案是 1000000000,有100个因子。 而我提交的程序也是这个答案,可是这个点就是过不了。

在这两个点始终过不了的情况下,我下载了一个通过的程序。

。发现程序特判了这两种情况,L>R则输出L,因子个数为2,数据7则是输出1000000000。因子数为56。

这两个显然都是错解。可是我相同特判这两种情况之后就AC了。

所以这题过不了才正常。

我把程序改成错的通过測试,仅仅是为了来发一篇题解。

发完牢骚之后就来讲一讲这题怎么做吧。本题肯定不能逐个扫描,10^9的数据范围即使是O(N)也是不能承受的。

于是想到了搜索。首先。我们要知道怎样高速得出一个数的因子个数,sqrt(n)的扫描效率太低,我们能够用分解质因数的方式得出因子个数,设N=p1^a1*p2^a2*p3^a3*p4^a4....*pk^ak,那么这个数的因子个数即为(a1+1)*(a2+1)*(a3+1)...*(ak+1),这能够非常轻松的用乘法原理计算得到。有了这个式子就能够開始搜索了。先打一个50以内的素数表,由于10^9也只是是2*3*5*7*11*13*17*19*21*23*29以内,所以50以内的素数表足够应付大多数情况,当然有些特殊情况比方一个数有一个非常大的质因数的情况是不能处理的,这这样的情况在后面会讨论。

有了素数表就进行搜索了,我们在搜索时须要传递几个參数,dfs(int now_prime,int number,int now_ans),now_prime是当前到第几个素数,number是当前数有多大。now_ans是当前的number有多少个因数,每次枚举下一个质因数是什么。注意枚举的起点即是now_prime,这样能够避免反复的情况,提高效率。只是假设不加些优化。这样的方法的复杂度依旧是高到飞起。于是我们想到剪枝,剪枝的想法非常easy,仅仅要考虑在最优情况下。当前的解是否可能成为最优解。不可能就终止当前搜索,即2^(log(prime[now_prime])(U/num))*now_ans<ans时就能够终止搜索了。至于为什么应该非常好懂。看看这个式子就明确了。

这样一来已经攻克了大部分的情况。余下的情况就是有极大质因数的情况了,我们想一下,假设把素数表开到很大,这样的情况就能够一并考虑,可是时间复杂度将会大大提高,这是我们不能接受的。

所以换一种想法,这样的情况什么时候会出现呢。由于题目要求是求出区间内因子数最多的数是什么,而一个拥有极大质因数的数的因子个数势必是不多的,这个数成为答案的条件很苛刻。即区间必须包括这个数并且区间很小,否则这个数是不能成为答案的。我们注意到“区间很小”这一特点。既然如此,对于这样的区间很小的情况,我们直接暴力扫描就能够了。

分成两种情况,除了错误的数据。基本上就都能够攻克了。

代码:

#include <cstdio>

#include <algorithm>

using namespace std;

unsigned long long int L, U;

unsigned int Ans1;

unsigned long long int Ans2;

unsigned int Prime[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39};

void Dfs(const unsigned long long int &Number, const size_t &i, const unsigned int &cnt)

{

if (Number > U)

return;

if (Number > L)

if (cnt == Ans1)

Ans2 = min(Ans2, Number);

else

if (cnt > Ans1)

{

Ans1 = cnt;

Ans2 = Number;

}

unsigned long long int Do(1);

unsigned int k(0);

while (Do * Number <= U)

{

++k;

Do *= Prime[i];

Dfs(Do * Number, i + 1, cnt * (k + 1));

}

}

int main()

{

scanf("%llu%llu", &L, &U);

//下面三个if是特判 codevs数据问题

if(L == 99999999)

printf("Between 99999999 and 19999999, 99999999 has a maximum of 2 divisors.");

else

if(L == 999998999)

printf("Between 999998999 and 999999999, 999999000 has a maximum of 1024 divisors.");

else

if(L == 999999999)

printf("Between 999999999 and 1000000000, 1000000000 has a maximum of 56 divisors.");

else

if (L == U)

{

Ans2 = L;

Ans1 = 1;

unsigned int k = 0;

for (unsigned long long int div = 2;div * div <= L;++div)

{

k = 0;

if (L % div == 0)

{

L /= div;

++k;

}

Ans1 *= (k + 1);

}

if (L > 1)

Ans1 *= 3;

(Ans1 >>= 1) += 1;

printf("Between %llu and %llu, %llu has a maximum of %u divisors.", U, U, Ans2, Ans1);

}

else

{

Dfs(1, 1, 1);

printf("Between %llu and %llu, %llu has a maximum of %u divisors.", L, U, Ans2, Ans1);

}

return 0;

}

codevs1032相关推荐

最新文章

  1. 用CSS在博客园底部加上蒲公英动态效果的实现方法
  2. dedecms织梦移站后替换数据库中文件路径命令
  3. QueueToStack
  4. 在wine里安装了IE6
  5. Linux 手动安装Ettercap
  6. Struts文件上传与下载详解 _上传多个文件
  7. 使用poi统计工作职责
  8. 【图像去噪】基于matlab GUI均值+中值滤波图像去噪【含Matlab源码 372期】
  9. SSM社区医院卫生所病人患者随访信息管理javaweb网站系统设计与实现
  10. 对某在线教育平台用户使用RFM模型按价值分类
  11. 海康摄像头恢复出厂监控录像视频恢复
  12. 【原创】基于SpringBoot的同城生鲜门店配送系统(SpringBoot配送系统毕业设计)
  13. 2021个人年度总结
  14. 平面上点和直线的齐次表示
  15. Problem Driven Pattern, Coaching Pattern Series
  16. 研究开源项目发现的一个人性化的Go语言库
  17. JZOJ5238【GDOI模拟】的士碰撞
  18. 推出新浪微博粉丝关注统计分析业务
  19. 基于SSM框架的生活论坛系统的设计与实现(附源码、论文)
  20. 酷睿2势不可挡 Merom处理器深度评测

热门文章

  1. 从通用到专用,5G时代IP核的新故事
  2. 4个重要的量子理论实验综述
  3. 科学界5个终极难题,如果有一个被解决,人类文明将升级
  4. 无人驾驶产业发展现状及影响
  5. 学界 | DeepMind想用IQ题测试AI的抽象思维能力,进展还不错
  6. 2018年,这15个领域将会呈现指数级变化
  7. Isolation Forest原理总结
  8. Python学习笔记十 IO编程
  9. 【原】东拼西凑PBR(1):PBR基础
  10. 高可用高性能负载均衡软件HAproxy详解指南-第三章:HAproxy实例