他们大神说这道题要什么手工开方
我想说,什么高端方法都弱爆了!
压位高精度+二分答案大法好
下面上我的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();
}