POJ2109-Power of Cryptography

全解题报告索引目录 -> 【北大ACM – POJ试题分类

转载请注明出处:http://exp-blog.com/2018/06/15/pid-409/

-------------------------------------------------------------------------


  1. /*
  2. Author: Exp
  3. Date: 2017-12-07
  4. Code: POJ 2109
  5. Problem: Power of Cryptography
  6. URL: http://poj.org/problem?id=2109
  7. */
  8. /*
  9. 【题意分析】
  10. 有指数函数 k^n = p ,
  11. 其中k、n、p均为整数且 1<=k<=10^9 , 1<=n<= 200 , 1<=p<10^101
  12. 给定 n 和 p ,求底数 k
  13. 【解题思路】
  14. 考虑到数值存储问题和精度问题,这题最直观的思路应该是使用 高精度算法 求解。
  15. 而事实上,这题也可用公式法求解,但需要一些技巧。
  16. 开方公式:k = n-sqrt(p)
  17. 但C++的数学函数库并没有提供k次方的开方函数,此时需要转换一下公式:
  18. k = p^(1/n)
  19. 对p开k次方等价于求p的1/k次方,此时我们就可以用pow函数求解了:
  20. k = pow(p, 1.0/n)
  21. 其实严格来说,如果这题没有限制 底数k 是整数,就不可能通过公式投机取巧。
  22. 简单来说,如果要使用公式法,那么题目中所有运算都只能基于double类型进行(int会溢出)
  23. double的取值范围为10^(-307)~10^308,但小数精度只有前16位(可自行搜索double的精度丢失问题).
  24. 也是就说,当我们用double存储p的时候, 它就已经开始出现误差, 其误差范围在10^(-15)的数量级左右.
  25. 此时套用公式对p开n次方根,须知开方运算是不会扩大误差范围的,
  26. 所以 n-sqrt(p) 的小数位误差范围依旧在10^(-15)的数量级以内,
  27. 又因为 k = n-sqrt(p) ,亦即计算所得的 n 的小数位误差范围也在10^(-15)的数量级以内,
  28. 显然这个误差级数仅会对n的小数部分存在影响,四舍五入后对整数部分是无影响的.
  29. 而题目已经限定了,n、k、p均是整数,因此使用公式法可以直接得到准确结果.
  30. 假若题目不存在整数限制,当n极大时,k会极小(无限迫近1,对小数精度极高),
  31. 此时公式法则会因为精度问题而失效.
  32. */
  33. #include <math.h>
  34. #include <iostream>
  35. using namespace std;
  36. int main(void) {
  37. double n , p;
  38. while( cin >> n >> p) {
  39. double tmp = pow(p, 1 / n); // p开n次方
  40. int k = floor(tmp + 0.5); // 四舍五入(+0.5后向下取整)
  41. cout << k << endl;
  42. }
  43. return 0;
  44. }




 

不要惊讶!程序就是这么短,这就是“技巧”与“算法”的差别

用double避开高精度算法,可以说是这题最大的BUG 

有兴趣的同学也可以去挑战 二分+高精

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值