uva 10023
2016-01-18 15:43
141 查看
这种大数开方的算法很神奇,步骤很简单,但是自己没有理解它的核心原理。
下面是转载的blog:
数学题(我更觉得是恶心模拟)
题意很清楚,就是给一个高精度整数,求它的平方根,数据保证一定是整数解
这个东西要用高精度各种搞(看过别人的报告说有些不用高精度,没心机看下去,自己硬是写了一堆高精度),主要就是模拟手算的方法
手算的方法这里说得很清楚了(希望看得到图片吧)
开根方法
笔算开根法:
例1:求
①将37625从个位起,向左每两位分一节:3,76,25
②找一个最大的数,使它的平方不大于第一节的数字,本题中得1(1的平方为1,而2的平方为4,大于3,所以得1).把1写在竖式中3的上方。
③将刚才所得的1平方写在竖式中3的下方,并相减,然后将76移写在本行(如图)
④将前面所得的1乘20,再加一个数a,写在竖式的左方(如图),并同时把a写在竖式的上方对准6。而这个所谓的a,是需要试验的,使它与(20+a)的积最大且不超过276.本题中所得的a为9
⑤用9乘29,再用276减去,所得的差写在下方
⑥继续反复运用步骤④和⑤。如果后面的数字不足,则补两个0,继续运算。如果最后的余数是0,则该数的算术平方根是有理数;如果被开方数是小数,小数部分在分节的时候是从十分位起,向右每两位小数分一节
————————————————————————————————
最后可以看到这题的通过率很低的,主要是这个模拟很多细节(个人觉得大牛莫鄙视),自己写了很久不敢提交,最终WA了一次,然后过了
建议本人的代码还是不要看了,很乱,主要是学会这个手算开根的方法,具体的代码还是自己实现吧
本人还没学java,应该用java的大数来写会方便很多
转载自:http://www.cnblogs.com/scau20110726/archive/2013/02/02/2890453.html
下面是转载的blog:
数学题(我更觉得是恶心模拟)
题意很清楚,就是给一个高精度整数,求它的平方根,数据保证一定是整数解
这个东西要用高精度各种搞(看过别人的报告说有些不用高精度,没心机看下去,自己硬是写了一堆高精度),主要就是模拟手算的方法
手算的方法这里说得很清楚了(希望看得到图片吧)
开根方法
笔算开根法:
例1:求
①将37625从个位起,向左每两位分一节:3,76,25
②找一个最大的数,使它的平方不大于第一节的数字,本题中得1(1的平方为1,而2的平方为4,大于3,所以得1).把1写在竖式中3的上方。
③将刚才所得的1平方写在竖式中3的下方,并相减,然后将76移写在本行(如图)
④将前面所得的1乘20,再加一个数a,写在竖式的左方(如图),并同时把a写在竖式的上方对准6。而这个所谓的a,是需要试验的,使它与(20+a)的积最大且不超过276.本题中所得的a为9
⑤用9乘29,再用276减去,所得的差写在下方
⑥继续反复运用步骤④和⑤。如果后面的数字不足,则补两个0,继续运算。如果最后的余数是0,则该数的算术平方根是有理数;如果被开方数是小数,小数部分在分节的时候是从十分位起,向右每两位小数分一节
————————————————————————————————
最后可以看到这题的通过率很低的,主要是这个模拟很多细节(个人觉得大牛莫鄙视),自己写了很久不敢提交,最终WA了一次,然后过了
建议本人的代码还是不要看了,很乱,主要是学会这个手算开根的方法,具体的代码还是自己实现吧
本人还没学java,应该用java的大数来写会方便很多
#include <cstdio> #include <cstring> #define N 1100 int big ,ans ,re ; int biglen,anslen,relen; int fun3(int *tmp , int tmplen) { //tmp是反序而re是正序的 if(tmplen<relen) return -1; //tmp<re else if(tmplen>relen) return 1; //tmp>re else { int i,j; //i指向tmp,j指向re for(i=tmplen,j=1; j<=relen; j++,i--) if(tmp[i] < re[j]) return -1; //tmp<re else if(tmp[i] > re[j]) return 1; //tmp>re return 0; //两者相等 } } void fun2(int *n1 ,int &n1len) { int i,j,a; int tmp ,tmplen,c,s; for(a=0; a<10; a++) { n1[1]=a; for(i=1,c=0; i<=n1len; i++) { s=n1[i]*a+c; tmp[i]=s%10; c=s/10; } if(c) { tmp[i]=c; tmplen=i;} else tmplen=i-1; //printf("tmplen=%d ",tmplen); //for(int i=tmplen; i>=1; i--) printf("%d",tmp[i]); printf("\n"); c=fun3(tmp,tmplen); //tmp和re比较大小 if(c==0 || c==1) //tmp=re或tmp>re,可以跳出 { if(c && a>0) ans[++anslen]=--a; else ans[++anslen]=a; //得到最新一位 break; } } if(a>=10) ans[++anslen]=a=9; if(a) { //printf("a=%d\n",a); memset(tmp,0,sizeof(tmp)); for(i=1,c=0,n1[1]=a; i<=n1len; i++) { s=n1[i]*a+c; tmp[i]=s%10; c=s/10; } if(c) { tmp[i]=c; tmplen=i;} else tmplen=i-1; //printf("tmplen=%d ",tmplen); //for(int i=tmplen; i>=1; i--) printf("%d",tmp[i]); printf("\n"); for(i=relen , j=1; i>=1; i--,j++) { if( re[i] >= tmp[j]) re[i]-=tmp[j]; else { re[i-1]--; re[i]=re[i]+10-tmp[j]; } } //消除re的前导0 for(i=1; i<=relen; i++) if(re[i]) break; for(j=1;i<=relen; j++,i++) re[j]=re[i]; relen=--j; } //printf("relen=%d ",relen); //for(i=1; i<=relen; i++) printf("%d",re[i]); printf("\n"); return ; } void fun1(int *n1 , int &n1len) { int i,j,c,s; //ans是正序保存的,最后要反序保存在n1中 n1[1]=0; c=0; for(j=anslen , i=2; j>=1; j--,i++) { s=ans[j]*2+c; n1[i]=s%10; c=s/10; } if(c) { n1[i]=c; n1len=i; } //最后还有进位 else n1len=i-1; //printf("n1len=%d ",n1len); //for(i=n1len; i>=1; i--) printf("%d",n1[i]); printf("\n"); } void solve() { int n1 ,n1len; //1.先将ans*20保存在n1中,涉及高精度乘法 //2.然后枚举a,使(n1+a)*a<re //n1+a涉及高精度加法,不过是高精度+一个个位数 //(n1+a)*a涉及高精度乘法,不过是高精度*一个个位数 //另外(n1+a)*a要与re高精度比较大小 fun1(n1,n1len); //计算ans*20,并保存在n1中 fun2(n1,n1len); //枚举a,并计算(n1+a)*a,并与re比较大小,并保存最新一位 //printf("anslen=%d ",anslen); //for(int i=1; i<=anslen; i++) printf("%d",ans[i]); printf("\n"); return ; } int main() { int T; scanf("%d",&T); while(T--) { char tmp ; scanf("%s",tmp+1); biglen=strlen(tmp+1); for(int i=1; i<=biglen; i++) big[i]=tmp[i]-'0'; /*******先处理得到第一位,并保存余数******/ memset(ans,0,sizeof(ans)); memset(re,0,sizeof(re)); int i,j,a,s,c; if(biglen%2) s=big[1] , c=1; //奇数位 else s=big[1]*10+big[2] , c=2; //偶数位 for(a=0; a*a<=s && a<10; ) a++; if(a>=10) ans[1]=a=9; else ans[1]=--a; anslen=1; s=s-a*a; if(s<10) { re[1]=s; relen=1; } else { re[2]=s%10; re[1]=s/10; relen=2; } //消除re的前导0 for(i=1; i<=relen; i++) if(re[i]) break; for(j=1;i<=relen; j++,i++) re[j]=re[i]; relen=--j; //printf("relen=%d ",relen); //for(i=1; i<=relen; i++) printf("%d",re[i]); printf("\n"); //printf("anslen=%d ",anslen); //for(int i=1; i<=anslen; i++) printf("%d",ans[i]); printf("\n"); /*******先处理得到第一位,并保存余数******/ while(c+1<biglen) //c每次跳两位 { re[relen+1]=big[c+1]; re[relen+2]=big[c+2]; relen+=2; //消除re的前导0 for(i=1; i<=relen; i++) if(re[i]) break; for(j=1;i<=relen; j++,i++) re[j]=re[i]; relen=--j; //printf("relen=%d ",relen); //for(i=1; i<=relen; i++) printf("%d",re[i]); printf("\n"); solve(); c+=2; } for(int i=1; i<=anslen; i++) printf("%d",ans[i]); printf("\n"); if(T) printf("\n"); } return 0; }
转载自:http://www.cnblogs.com/scau20110726/archive/2013/02/02/2890453.html
相关文章推荐
- Java Web学习总结(16)——JSP的九个内置对象
- 开源框架】Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发
- pwnable.kr解题write up —— Toddler's Bottle(一)
- Android仿易信界面SlidingMenu左右滑动
- Redis 3.0的集群部署
- Java Web学习总结(16)——JSP的九个内置对象
- Android SDK开发包国内下载地址
- ibatis resultMap result中的resultMap问题
- Java7的异常处理新特性-addSuppressed()方法等
- 2015年最值得关注的8款用户界面新品
- fopen与fopen_s的比较
- Deepin 安装RVM ,ruby, rails
- Eclipse智能提示及快捷键
- ANSI转化UTF-8的方法
- Android 开发绕不过的坑:你的 Bitmap 究竟占多大内存?
- 在客户端使用JSONP做跨域请求
- Android系统之路(初识MTK) ------ 默认第一次开机屏幕亮度/日期格式/picture makeer model
- HDU 4974 A simple water problem(贪心)
- csv 导 mysql
- 【linux】命令