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));}


原创粉丝点击