codevs1032
题目地址: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的更多相关文章
- mysql基本操作【重要】
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAuYAAAVeCAIAAACyxWmSAAAgAElEQVR4nOydT0wbV/vvZzm7YXd2zI ...
随机推荐
- ckeditor小记
widget 只要创建都会执行 init函数,可以绑定事件,但是如果widget释放了,其上绑定的时间也就没有了
- 乘法逆元__C++
在开始之前我们先介绍3个定理: 1.乘法逆元(在维基百科中也叫倒数,当然是 mod p后的,其实就是倒数不是吗?): 如果ax≡1 (mod p),且gcd(a,p)=1(a与p互质),则称a关于模p ...
- 移动端H5多平台分享实践--摘抄
作者:大漠 日期:2018-01-20 点击:628 mobile 编辑推荐: 掘金是一个高质量的技术社区,从 CSS 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货. 点击 ...
- Xcode 如何计算整个项目的代码行数
参考链接:https://www.cnblogs.com/sunfuyou/p/7921538.html 1.打开终端 2.cd 空格 将工程的文件夹拖到终端上,回车,此时进入到工程的路径 此时已经进 ...
- AC日记——拍照 洛谷 P3410
题目描述 小B有n个下属,现小B要带着一些下属让别人拍照. 有m个人,每个人都愿意付给小B一定钱让n个人中的一些人进行合影.如果这一些人没带齐那么就不能拍照,小B也不会得到钱. 注意:带下属不是白带的 ...
- AC日记——传纸条 洛谷 P1006
题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的是 ...
- 基于python的性能测试工具–locust
现在有很多的性能测试工具,比如说我们熟悉的loadrunner.jmeter.ab.webbench等等,这些工具如果对一个没用过的朋友来说,学习起来比较不容易,但是如果你能看懂python代码,会写 ...
- HDU 1045 Fire Net 状压暴力
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others) ...
- free如何知道释放内存长度:vs与glibc分配内存时编译器内部处理
鉴于网上这个资料实在太少,将以前整理过却未完全的一篇文章贴出来,希望大牛指正vs下内存管理方式.可联系gaoshiqiang1987@163.com vs分配内存 vs没有源码,编译器在分配内存时,分 ...
- bzoj 1835/luogu P2605 : [ZJOI2010]base 基站选址
题目描述 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄不超过Si的范 ...