SGU 111 Very simple problem
来源:互联网 发布:淘宝上怎么开充值店 编辑:程序博客网 时间:2024/04/29 12:37
叫Very simple problem的通常都不简单。。。
此题就是让你求一个数的平方根取整。但是这个数特别大10^1000。所以不能(int)sqrt。。
查了一下解题报告,有两种方法。
第一种是模拟徒手开方,第二种是高精度+二分。
这里先整理徒手开方的解法。
(1)把被开方数(如22146436)从右向左每隔两位用撇号分开(如22’14’64’36); (2)从左边第一段(如22)求得算术平方根的第一位数字(如4) ; (3)从第一段减去这第一位数字的平方(如22-42=6),再把被开方数的第二段写下来,作为第一个余数(如614); (4)把所得的第一位数字(如4)乘以20,去除第一个余数所得的商的整数部分(如614÷(4×20)=7.675的整数部分7)作为试商(注:如果这个整数部分大于或者等于10,就改用9作试商,如果第一个余数小于第一位数字乘以20的积,则得试商0); (5)把第一位数字的20倍加上试商的和,乘以这个试商所得值不大于第一个余数时(如(4×20+7)×7=609≤614),这个试商就是算术平方根的第二位数字(注:如果所得的积大于余数时,就要把试商减去1再试,直到积小于或者等于余数为止); (6)用第一个余数减去第一位数字的20倍加上试商的和乘以该试商所得值的差(如614-609=5),往后用同样的方法,继续求算术平方根的其他各位数字。
把这种过程编程实现即可。
如果位数是奇数,则在最高位前加一个0,使其依然可以被两两分割。
省去试商的过程,从9开始枚举到0,找到t,使得目前的 (ans*20+t)*t 不大于当前余数。
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>using namespace std;bool Check(char *rem,int s,int e,char *ans,int la,char *s3){ int ls3,ite,i,n; char s1[2000],s2[2000]; strcpy(s1,rem); strcpy(s2,ans); s3[0]=ans[la-1]; n=s3[0]-'0'; ite=0; ls3=1; //乘以20 for (i=la-2; i>=0; i--) { ite+=(s2[i]-'0')*2; s3[ls3]=ite%10+'0'; ite/=10; ls3++; } if (ite != 0) { s3[ls3]=ite+'0'; ls3++; } while (s3[ls3-1] == '0' && ls3 > 1) ls3--; s3[ls3]='\0'; ite=0; //加上n后,再乘以n for (i=0; i<ls3; i++) { ite+=(s3[i]-'0')*n; s3[i]=ite%10+'0'; ite/=10; } while (ite != 0) { s3[ls3]=ite%10+'0'; ite/=10; ls3++; } while (s3[ls3-1] == '0' && ls3 > 1) ls3--; s3[ls3]='\0'; strrev(s3); if (ls3 == 1) { s3[ls3]=s3[0]; s3[0]='0'; ls3++; } //判断大小 if (e-s < ls3) { return false; } else if (e-s > ls3) { return true; } else //位数相等的情况下 { for (i=0; i<ls3; i++) { if (rem[s+i] < s3[i]) return false; else if (rem[s+i] > s3[i]) return true; } return true; }}void ChangeRem(char *rem,int *s,int e,char *s3){ int ls,i; i=e-1; ls=strlen(s3)-1; while (ls >= 0) { if (rem[i] >= s3[ls]) { rem[i]-=s3[ls]; rem[i]+='0'; } else { rem[i-1]-=1; rem[i]=(rem[i]-s3[ls])+10+'0'; } ls--; i--; } while (rem[(*s)] == '0') { (*s)++; }}char *BigSqrt(char *str){ int i,j,ls,la,lr,sr; char num[2000],ans[2000],rem[2000],tc,tstr[2000]; la=0; lr=0; sr=0; ls=strlen(str); if ((ls&1) == 1) //如果位数是奇数,则在最高位加0 { num[0]='0'; strcpy(num+1,str); ls++; } else { strcpy(num,str); } for (i=0; i<ls; i+=2) { rem[lr]=num[i]; rem[lr+1]=num[i+1]; lr+=2; tc='9'+1; while (tc--) //从9到0 { ans[la]=tc; ans[la+1]='\0'; if (Check(rem,sr,lr,ans,la+1,tstr) == true) //判断(ans*20+t)*t是否不大于当前余数 { //满足,对当前余数remaider-(ans*20+t)*t la++; ChangeRem(rem,&sr,lr,tstr); break; //找到了平方根的这一位上的数,直接跳出 } } } return ans;}int main(){ char str[2000]; scanf("%s",str); printf("%s",BigSqrt(str));}
- SGU 111 Very simple problem
- SGU 111 Very simple problem
- SGU 111 Very simple problem
- SGU 111 Very simple problem(高精度)
- [SGU]111. Very simple problem
- sgu 111 Very simple problem 高精开平方
- SGU 111 Very simple problem(高精度+二分)
- 1166 Very Simple Problem
- [Java]Very simple problem
- sgu111:Very simple problem
- 111. Very simple problem
- SGU111 Very simple problem
- FOJ 1350 Very Simple Problem
- FZU 1350 Very Simple Problem
- POJ 2535 Very Simple Problem
- poj 2535 Very Simple Problem
- 【FOJ 1350】 Very Simple Problem
- foj 1350 Very Simple Problem
- Linux的简介与安装
- Java 中字符串的格式化
- iPhone开发【五】常用控件之Slider(不使用xib构建UI)
- PreparedStatement查询oracle char类型解决方案
- Oracle 游标与绑定变量
- SGU 111 Very simple problem
- c# 日志
- Linux 多线程同步之哲学家用餐问题
- Android 中文API (46) —— SimpleAdapter
- iPhone开发【六】常用控件之Picker View
- HTML+CSS制作一像素边框
- iPhone开发【七】常用控件之表TableView
- linux subsys_initcall
- SiteMesh笔记