?POJ 2109 -- Power of Cryptography
Posted Amysear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了?POJ 2109 -- Power of Cryptography相关的知识,希望对你有一定的参考价值。
Power of Cryptography
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 26622 | Accepted: 13301 |
Description
This problem involves the efficient computation of integer roots of numbers.
Given an integer n>=1 and an integer p>= 1 you have to write a program that determines the n th positive root of p. In this problem, given such integers n and p, p will always be of the form k to the nth. power, for an integer k (this integer is what your program must find).
Input
Output
Sample Input
2 16
3 27
7 4357186184021382204544
Sample Output
4
3
1234
Source
用pow函数求解:
k = pow(p, 1.0/n)
double的取值范围为10^(-307)~10^308,但小数精度只有前16位, 其误差范围在10^(-15)的数量级左右.
这个误差级数仅会对n的小数部分存在影响,四舍五入后对整数部分是无影响的.
而题目已经限定了,n、k、p均是整数,因此使用公式法可以直接得到准确结果.
假若题目不存在整数限制,当n极大时,k会极小(无限迫近1,对小数精度极高),
此时公式法则会因为精度问题而失效.
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 int main() 5 { 6 double n,p; 7 while(cin>>n>>p) 8 { 9 double k; 10 k = pow(p,1.0/n); 11 cout<<k<<endl;; 12 } 13 return 0; 14 }
2)使用 高精度算法 + 二分法
首先,想要求 kn = p的k,不使用如上计算方法的公式法,只能枚举k,进行高精度乘法。
寻找k的方法,可以使用二分法。
那k的范围是什么呢,考虑样例7 4357186184021382204544,p是22位,22/7=3~4,向上取整,所以p是一个四位数,即1000<=p<=9999。
在这个范围进行二分查找,就可以找到k。
关于高精度算法,看过一个博文,想了解详情的可以移步=》从零开始学算法:高精度计算
c++ / % 四舍五入 向上取整ceil 向下取整floor
1 #include<iostream> 2 #include<math.h> 3 #include<cstring> 4 #include<stdio.h> 5 using namespace std; 6 const int maxp = 104; 7 //const int maxk = 12; 8 int p[maxp]; 9 int k[maxp]; 10 11 int Compare(int a[],int b[]) 12 {///如果相等返回0,>返回1,<返回-1 13 if(a[0] > b[0]) return 1; 14 else if(a[0] < b[0]) return -1; 15 else//位数相等,需要逐位判断 16 { 17 for(int i=a[0];i>0;i--) 18 { 19 if(a[i]>b[i]) return 1; 20 else if(a[i] < b[i]) return -1; 21 } 22 } 23 return 0; 24 } 25 26 void bigEqual(int n) 27 {///计算k^n,将结果存在k中 28 int temp[maxp];int Equal[maxp]; 29 memset(Equal,0,sizeof(Equal));//用来存放另一个乘数 30 memset(temp,0,sizeof(temp));//用来存放每次相乘的结果 31 for(int i = 0;i<=k[0];i++) 32 Equal[i] = k[i]; 33 for(int turn = 1;turn<n;turn++) 34 { 35 for(int i=1;i<=k[0];i++)///计算k * Equal,存在temp中 36 { 37 for(int j=1;j<=Equal[0];j++) 38 { 39 temp[i+j-1] += k[i]*Equal[j]; 40 } 41 temp[0] = Equal[0]+k[0]-1; 42 for(int j=1;j<=temp[0];j++)///处理进位 43 { 44 if(temp[j]>=10) 45 { 46 temp[j+1] += temp[j]/10;temp[j] = temp[j]%10; 47 } 48 } 49 while(temp[temp[0]+1]) 50 { 51 temp[0]++; 52 temp[temp[0]+1] = temp[temp[0]]/10; 53 temp[temp[0]] = temp[temp[0]]%10; 54 } 55 } 56 for(int m=0;m<=temp[0];m++) 57 Equal[m] = temp[m];//转存temp作为下一次的乘数 58 memset(temp,0,sizeof(temp)); 59 } 60 for(int i=0;i<=Equal[0];i++) 61 k[i] = Equal[i]; 62 } 63 64 int main() 65 { 66 char s[maxp]; 67 int n; 68 while(scanf("%d %s",&n,&s) != EOF) 69 { 70 memset(p,0,sizeof(p)); 71 ///将p处理成数组 72 p[0] = strlen(s);//第一位存储p的位数 73 for(int i=p[0]-1;i>=0;i--) 74 { 75 p[p[0]-i] = s[i]-\'0\'; 76 } 77 int kLength = ceil((double)p[0]/n);//向上取整 78 int Min = 1,Max = 9; 79 for(int i=1;i<kLength;i++) 80 { 81 Min *=10; 82 } 83 for(int i=1;i<kLength;i++) 84 { 85 Max *=10;Max += 9; 86 } 87 ///使用二分法查找 88 double Mid = (Min+Max)/2; 89 for(int low = Min,up = Max;low<=up;) 90 { 91 memset(k,0,sizeof(k)); 92 ///给k赋值为Mid 93 int i=1;int temp = Mid; 94 while(temp) 95 { 96 k[i] = temp%10; 97 temp = temp/10; 98 i++; 99 } 100 k[0] = i-1;//k[0]存储k的长度 101 bigEqual(n);///计算k^n,将结果存储在k中 102 int j = Compare(k,p); 103 if(j == 0)//相等 104 break; 105 else if(j == 1)//k>p,向Mid的左侧查找 106 { 107 up = Mid-1;Mid = (low+up)/2; 108 } 109 else{//k<p,向Mid的右侧查找 110 low = Mid+1;Mid = (low+up)/2; 111 } 112 } 113 cout<<Mid<<endl; 114 } 115 return 0; 116 }
告诫自己:
s不可以用String类型
string不可以用cin>>进行赋值
以上是关于?POJ 2109 -- Power of Cryptography的主要内容,如果未能解决你的问题,请参考以下文章
?POJ 2109 -- Power of Cryptography
POJ 2109 Power of Cryptography
POJ_2109 Power of Cryptography 数学