sgu 111 分类: sgu 2015-02...

sgu111

题意:大整数开方

解法:直接 二分+高精度(压位)

C语言手写高精度代码量还是比较大呀~

顺便发现了开方运算的一些神奇方法!

http://www.cnblogs.com/pkuoliver/archive/2010/10/06/1844725.html

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define size 4
#define Bit  10000
#define Half 5000 
#define MAXN 300

struct number{int n[MAXN],l;}ans={0},mid={0},l={0},r={0},p={0}; 

char ch[MAXN*4]={'\0'};

inline struct number plus(struct number x)
{
    int i;

    x.n[1]++;

    for(i=1;i<=x.l;i++)
    {
        if(x.n[i]>=Bit)
          x.n[i]-=Bit,x.n[i+1]++;
        else   break;  
    }

    if(x.n[x.l+1])x.l++;

    return x;
}
inline int compare(struct number x,struct number y)
{
    if(x.l > y.l)return 1;
    else if(x.l < y.l)return -1;
    else
    {
       int i;   

       for(i=x.l;i>=1;i--)  
      {
        if(x.n[i] > y.n[i])return 1;
        else if(x.n[i] < y.n[i])return -1;
        else continue;
      }

      return 0;
    }

}
int max(int a,int b){return (a>b)?a:b;}

inline struct number add(struct number x,struct number y)
{
    int i,tl;

    tl=max(x.l,y.l);

    for(i=1;i<=tl;i++)
    {
        x.n[i]+=y.n[i];

        if(x.n[i]>=Bit)
          x.n[i]-=Bit,x.n[i+1]++;
    }

    if(x.n[tl+1])x.l=tl+1;
    else         x.l=tl;

    return x;
}

inline struct number divi(struct number x)
{
    int i;struct number ret={0};

    for(i=x.l;i>=1;i--)
    {
        ret.n[i]+=x.n[i]>>1;

        if(x.n[i]&1)
          ret.n[i-1]+=Half;
    }
    ret.n[0]=0;

    if(ret.n[x.l])ret.l=x.l;
    else          ret.l=x.l-1;

    return ret;
}
inline struct number powi(struct number x)
{
    struct number ret={0};
    int i,j;

    ret.l=x.l*2-1;

    for(i=1;i<=x.l;i++)
      for(j=1;j<=x.l;j++)
    {
        ret.n[i+j-1]+=x.n[i]*x.n[j];

        ret.n[i+j]+=ret.n[i+j-1]/Bit;
        ret.n[i+j-1]%=Bit;
    }

    for(i=1;i<=ret.l;i++)
    {
        ret.n[i+1]+=ret.n[i]/Bit;
        ret.n[i]%=Bit;
    }
    while(ret.n[ret.l+1])
    {
        ret.l++;
        ret.n[ret.l+1]+=ret.n[ret.l]/Bit;
        ret.n[ret.l]%=Bit;
    }

    return ret;
} 

inline void prt()
{
    int i,t,tl;

    printf("%d",ans.n[ans.l]);
    for(i=ans.l-1;i>=1;i--)
    {
        t=ans.n[i],tl=0;

        if(!t)tl=1;
        else
          while(t)
         {
            t/=10;tl++;
         }

        for(t=1;t<=size-tl;t++)printf("0");

        printf("%d",ans.n[i]); 
    }

}
int main()
{
    int i,j,k;

    #ifndef ONLINE_JUDGE
    freopen("sgu111.in","r",stdin);
    freopen("sgu111.out","w",stdout);
    #endif

    scanf("%s",ch);

    for(i=strlen(ch)-1,j=1;i>=0;i-=size,j++)
      for(k=max(0,i-size+1);k<=i;k++)
    {
       p.n[j]*=10,p.n[j]+=ch[k]-'0';
    }
    p.l=j-1;

    /*

    while(l+1!=r)
    {
        mid=(l+r)>>1;

        if(mid*mid>p)
        {
            r=mid;
        }
        else
        {
            l=mid;
        }

    }

    ans=l;

    */
    l.l=1;l.n[1]=1;
    r.l=(p.l+1)/2+1;r.n[r.l]=1;

    while(compare(plus(l),r))
    {
       mid=divi(add(l,r));  

       if(compare(powi(mid),p)>0)
          r=mid;
       else
          l=mid;
    }
    ans=l;

    prt();

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/dashgua/p/4723116.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值