大数开根
模板1:对于长度为 n 的数,其算术平方根长度为 n/2(n 为偶数) 或 n/2+1(n 为奇数),然后从高位到低位枚举每位即可得出结果;
代码:
1 #include<iostream> 2 #include<string> 3 #include<string.h> 4 using namespace std; 5 6 const int MAXN = 1e3+10; 7 string s; // n,m; 8 int len; // 记录开根号后大数的位数; 9 10 int sqrts[MAXN]; 11 int a[MAXN], temp[MAXN], ans[MAXN]; 12 13 int compare(int a[], int b[], int len1, int len2){ 14 if(len1 > len2) return 1; 15 else if(len1 < len2) return -1; 16 for(int i=len1-1; i>=0; i--){ 17 if(a[i] > b[i]) return 1; 18 else if(a[i] < b[i]) return -1; 19 } 20 return 0; 21 } 22 23 // 计算sqrta[]*sqrtb[],len1,len2分别为sqrta,sqrtb的长度;返回结果位数; 24 int multi(int *ans, int A[], int B[], int len1, int len2){ 25 for(int i=0; i<=MAXN; i++) ans[i]=0; // 对于传址ans,用memset没法初始化; 26 for(int i=0; i<len1; i++){ 27 for(int j=0; j<len2; j++){ 28 ans[i+j] += A[i]*B[j]; 29 } 30 } 31 for(int i=0; i<len1+len2; i++){ 32 ans[i+1] += ans[i]/10; 33 ans[i] %= 10; 34 } 35 int i; 36 for(i=len1+len2; i>=0; i--){ 37 if(ans[i]) break; 38 } 39 return i+1; 40 } 41 42 // 将s开根号,保存在A(倒序存储)中,并且返回开根号后s的位数; 43 int get_sqrt(int *A, string s){ 44 memset(A, 0, sizeof(A)); 45 memset(a, 0, sizeof(a)); 46 int len1 = s.size(); 47 int len2 = len1>>1; 48 if(len1 & 1) len2 += 1; 49 for(int i=0,j=s.size()-1; i<s.size(); i++,j--){ //翻转 50 a[j]=s[i]-'0'; 51 } 52 for(int i=len2-1; i>=0; i--){ // 从最高位开始试; 53 int flag, lenMul=1; 54 memset(temp, 0, sizeof(temp)); 55 while((flag=compare(temp, a, lenMul, len1))==-1){ 56 A[i]++; 57 lenMul=multi(temp, A, A, len2, len2); 58 for(int k=0; k<len2; k++){ 59 cout << A[k]; 60 } 61 cout << endl; 62 } 63 if(flag==0) break; 64 else if(flag==1) A[i]--; 65 } 66 return len2; 67 } 68 69 int main(void){ 70 cin >> s; 71 len = get_sqrt(sqrts, s); 72 for(int i=len-1; i>=0; i--){ 73 cout << sqrts[i]; 74 } 75 cout << endl; 76 return 0; 77 }
我就是我,颜色不一样的烟火 --- geloutingyu