先附上大佬博客Orz:https://blog.csdn.net/snailset/article/details/26752435
太久没刷题思维也跟不上了。。看了题解后自己又分析了一遍,如下图:
接下来就是大数运算了,知道Java有现成的库,但我没学过Java啊QAQ...只能用C硬怼了。。之前曾经弄过,就是字符串操作,另外开方的时候注意有技巧,不能暴搜。。但我代码能力急剧下降,这么简单的问题debug了好久55555...主要坑点都在代码里了。。附上通过代码(又丑又长QAQ):
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int MAX=1005;
char a[MAX],b[MAX];
char sa[MAX/2],sb[MAX/2];
char c[MAX];
void Rev(char *s)
{
int l=strlen(s);
for(int i=0,j=l-1;i<=j;i++,j--)//注意j--!!
{
char tmp=s[i];
s[i]=s[j];s[j]=tmp;
}
}
void Mul(char a[],char b[],char c[])
{
Rev(a);Rev(b);//逆序
int la=strlen(a);
int lb=strlen(b);
int lc=la+lb;//c可能的最长位数
int tmp[MAX];
memset(tmp,0,sizeof(tmp));
for(int i=0;i<la;i++)
{
int k1=a[i]-'0';
for(int j=0;j<lb;j++)
{
int k2=b[j]-'0';
tmp[i+j]+=(k1*k2);//先不管进位,注意是"+="!
}
}
for(int i=0;i<lc;i++)
{
if(tmp[i]>=10) //注意是">="10!!
{
tmp[i+1]+=(tmp[i]/10);//注意是"+="
tmp[i]%=10;
}
}
if(tmp[lc-1]==0)//最高位没有进位
lc--;
for(int i=0;i<lc;i++)
c[i]=tmp[i]+'0';
c[lc]='\0';
//cout<<"lc="<<lc<<" c="<<c<<endl;
Rev(c);//逆序
}
int check(char a[],char b[])
{
int la=strlen(a);
int lb=strlen(b);
if(la>lb) return 1;
else if(la<lb) return -1;
else for(int i=0;i<la;i++)
{
if(a[i]>b[i]) return 1;
else if(a[i]<b[i]) return -1;
}
return 0;
}
void Sqrt(char s[],char t[])
{
int l=strlen(s);
if(l%2)//奇数
l=l/2+1;
else
l/=2;
for(int i=0;i<l;i++)
t[i]='0'; //注意是符号0!!
t[l]='\0';
//cout<<"l="<<l<<endl;
char t1[MAX],t2[MAX];
char tmp[MAX];
for(int i=0;i<l;i++)
{
for(int k=1;k<=9;k++)
{
t[i]=k+'0';
strcpy(t1,t);strcpy(t2,t);
Mul(t1,t2,tmp);//注意产生两个副本!不然原始的t数组都改乱了!
//cout<<" t="<<t<<" tmp="<<tmp<<" s="<<s<<endl;
//两个正序的字符串,注意不能直接strcmp!
if(check(tmp,s)>0) //t*t>s
{
t[i]--;
break;
}
if(check(tmp,s)==0)
return;
}
}
}
int main()
{
scanf("%s%s",a,b);
Sqrt(a,sa);
//cout<<"a="<<a<<" sa="<<sa<<endl;
Sqrt(b,sb);
//cout<<"b="<<b<<" sb="<<sb<<endl;
Mul(sa,sb,c);
//cout<<"c="<<c<<endl;
int lc=strlen(c);
for(int i=0;i<lc;i++)
printf("%c",c[i]);
return 0;
}