【Vijos-P1172】反质数-DFS
2016-08-11 18:13
211 查看
题目大意:一个正整数,如果它的约数个数比所有比它小的正整数的约数个数都大,则称这个数为反质数,求不超过N(1≤N≤2000000000)的最大反质数。
做法:当初一拿到这题瞬间蒙了,不知道这是什么鬼,后来了解约数定理之后发现这就是个裸的DFS啊!约数定理是指,一个数的约数个数等于它分解质因子后的每个质因子的指数+1的乘积,用一个具体的例子来说,例如1800这个数,分解质因子后得到的式子为2^3*3^2*5^2,2的指数是3,3的指数是2,5的指数是2,因此1800的约数个数为:(3+1)*(2+1)*(2+1)=36个。这个定理可以很容易的用组合数学的方法来证明。然后就可以愉快的DFS了,思路非常简单,从小到大枚举质因子和它的指数,记录下满足条件的最大数字和它的约数个数即可。需要注意的是解的替换,如果当前数字的约数个数比前面求出的解的约数个数大,则必须替换,因为在这种情况下,说明当前数字比已知解更优或已知解不满足条件。如果当前数字的约数个数与前面求出的解的约数个数相等而数字比已知解小,则说明已知解不满足条件,也要替换。可以证明搜索的深度不超过30。
以下是本人代码:
做法:当初一拿到这题瞬间蒙了,不知道这是什么鬼,后来了解约数定理之后发现这就是个裸的DFS啊!约数定理是指,一个数的约数个数等于它分解质因子后的每个质因子的指数+1的乘积,用一个具体的例子来说,例如1800这个数,分解质因子后得到的式子为2^3*3^2*5^2,2的指数是3,3的指数是2,5的指数是2,因此1800的约数个数为:(3+1)*(2+1)*(2+1)=36个。这个定理可以很容易的用组合数学的方法来证明。然后就可以愉快的DFS了,思路非常简单,从小到大枚举质因子和它的指数,记录下满足条件的最大数字和它的约数个数即可。需要注意的是解的替换,如果当前数字的约数个数比前面求出的解的约数个数大,则必须替换,因为在这种情况下,说明当前数字比已知解更优或已知解不满足条件。如果当前数字的约数个数与前面求出的解的约数个数相等而数字比已知解小,则说明已知解不满足条件,也要替换。可以证明搜索的深度不超过30。
以下是本人代码:
#include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; long prime[21]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47}; long long n,maxi=0,maxn=999999999; //maxn,maxi:满足条件的最大数和它的约数个数 void search(long long x,long long s,long long p) //x,s,p:当前数字,当前数字的约数个数和枚举到的质因子序号 { if (s>maxi) {maxi=s;maxn=x;} if (s==maxi&&x<maxn) maxn=x; if (s<maxi&&x>maxn) return; int total=0; while(x*prime[p]<n) { total++; x*=prime[p]; search(x,s*(total+1),p+1); } } int main() { cin >> n; search(1,1,1); cout << maxn; return 0; }
相关文章推荐
- css3笔记
- Registry key 'Software\JavaSoft\Java Runtime Environment'\CurrentVersion' ha
- Linux添加/删除用户和用户组
- Garbage Collectors
- c# 对excel数据进行打印
- POJ 1611 记录节点数的并查集
- Unreal 蓝图显示鼠标
- 反射机制
- Servlet开发(一)
- 【百度校招2016】蘑菇阵
- nginx解析php页面
- 看懂此文,不再困惑于 JS 中的事件设计
- 七、Ubuntu 关机或者重启
- C语言学习11
- iOS SDwebimage清除缓存
- 【HDU】-1087-Super Jumping! Jumping! Jumping!(DP)
- java获取中文对应的全拼音
- 酷酷的 CSS3 三角形运用
- Sqli-labs less 63
- 使用反射机制调用service层方法Autowired标签自动注入失败