他們大神說這道題要什麼手工開方
我想說,什麼高端方法都弱爆了!
壓位高精度+二分答案大法好
下面上我的2B代碼
本來我沒有壓位的呢,結果發現不壓位會TLE
然後我就壓了5位,結果乘法爆int了
然後我就果斷開longlong壓7位(不敢壓8位的蒟蒻)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define L 10000000
#define SIZE 1500
/*
暴力開方:高精度開方X
我會說2011普及組小孩都會這個!
哎呀 普通二分過不了惹
壓位大法好!!
egawnelkgnaweroibaweriognaweirgbawerohnawerhawenkhoweWHZrabhio
*/
typedef struct node
{
int len;
long long num[SIZE];
}big;
char s[SIZE]={0};
big target;
//len表示大整數的位數,num[i]--表示第i低位如 num[1]--個位
void open()
{
freopen("111.in","r",stdin);
freopen("111.out","w",stdout);
}
void close()
{
fclose(stdin);
fclose(stdout);
}
big times(big a,big b)
//計算兩數之積
{
int i,j;
big ans;
memset(ans.num,0,sizeof(ans.num));
/*相乘*/
for (i=1;i<=a.len;i++)
for (j=1;j<=b.len;j++)
ans.num[i+j-1]+=a.num[i]*b.num[j];
/*進位*/
for (i=1;i<=a.len+b.len;i++)
{
ans.num[i+1]+=ans.num[i]/L;
ans.num[i]%=L;
if (ans.num[a.len+b.len]>0)
ans.len=a.len+b.len;
else
ans.len=a.len+b.len-1;
}
return ans;
}
big add(big a,big b)
//計算大整數a+b
{
int i;
big ans;
memset(ans.num,0,sizeof(ans.num));
/*相加*/
ans.len=MAX(a.len,b.len);
for (i=1;i<=ans.len;i++)
{
ans.num[i]+=a.num[i]+b.num[i];
ans.num[i+1]+=ans.num[i]/L;
ans.num[i]%=L;
}
if (ans.num[ans.len+1]>0)
ans.len++;
return ans;
}
big ave(big a,big b)
//計算[(a+b)/2]
{
int i;
big ans;
ans=add(a,b);//先算和
for (i=ans.len;i>=2;i--)
{
ans.num[i-1]+=(ans.num[i]%2)*L;
ans.num[i]=ans.num[i]/2;
}
ans.num[1]=ans.num[1]/2;
if (ans.num[ans.len]==0)
ans.len--;
return ans;
}
big addd(big a,int n)
//計算大整數a+n(單精度)
{
int i;
a.num[1]+=2;
for (i=1;i<=a.len && (a.num[i])>=L;i++)
{
a.num[i+1]+=a.num[i]/L;
a.num[i]%=L;
}
if (a.num[a.len+1]>0)
a.len++;
return a;
}
int da(big a,big b)
//判斷a>b麼
{
int i;
if (a.len<b.len)
{
return 0;
}
for (i=a.len;i>=1;i--)
if (a.num[i]!=b.num[i])
break;
if (a.num[i]<=b.num[i])
return 0;
else
return 1;
}
void init()
{
int i,j,k;
int ten[10]={0,1,10,100,1000,10000,100000,1000000,10000000};
scanf("%s",s);
target.len=strlen(s);
/*
7位一存
*/
for (i=target.len-1,j=1,k=1;i>=0;i--,k++)
{
if (k==8)
{
k=1;
j++;
}
target.num[j]+=(s[i]-'0')*ten[k];
}
target.len=j;
}
void print(big a)
{
int i;
printf("%d",a.num[a.len]);
for (i=a.len-1;i>=1;i--)
{
if (a.num[i]<1000000) printf("0");
if (a.num[i]<100000) printf("0");
if (a.num[i]<10000) printf("0");
if (a.num[i]<1000) printf("0");
if (a.num[i]<100) printf("0");
if (a.num[i]<10) printf("0");
printf("%d",a.num[i]);
}
printf("\n");
}
void erfen()
{
big left={0},right={0},middle;
left.len=1;
left.num[1]=1;
right=target;
do
{
middle=ave(left,right);
//printf("mid=");print(middle);
//printf("mid^2=");print(times(middle,middle));
if (da(times(middle,middle),target)==0)
{
left=middle;
}
else
right=middle;
}
while(da(addd(left,2),right)==0);
/*
for (i=left.len;i>=1;i--)
printf("%d",left.num[i]);
*/
print(left);
}
int main()
{
open();
init();
erfen();
close();
}