1. 程式人生 > >高精度練習之超大整數開根

高精度練習之超大整數開根

題目描述 Description

給出一個正整數n,求n開根號後的整數部分的值。n的位數不超過1000位。
輸入描述 Input Description

讀入一個不超過1000位的正整數n。
輸出描述 Output Description

輸出所求答案
樣例輸入 Sample Input

17
樣例輸出 Sample Output

4
資料範圍及提示 Data Size & Hint

n為不超過1000位的正整數 滿足 1<=n <10^1000
首先我是一個蒟蒻23333所以我不會一些奇怪的東西比如暴力二分做這個題
then
有一個奇怪的東西叫做手動開根:
手動開根號的基本方法:
1. 將被開方數從右向左每隔2位用撇號分開;
2. 從左邊第一段求得算數平方根的第一位數字;
3. 從第一段減去這個第一位數字的平方,再把被開方數的第二段寫下來,作為第一個餘數;
4. 把所得的第一位數字乘以20,去除第一個餘數,所得的商的整數部分作為試商(如果這個整數部分大於或等於10,就改用9左試商,如果第一個餘數小於第一位數字乘以20的積,則得試商0);
5. 把第一位數字的20倍加上試商的和,乘以這個試商,如果所得的積大於餘數時,就要把試商減1再試,直到積小於或等於餘數為止,這個試商就是算數平方根的第二位數字;
6. 用同樣方法繼續求算數平方根的其他各位數字。

example:
這裡寫圖片描述
so 我們就獲得了一種神奇的方法來做這道題切擁有更快的速度和更高的複雜度。

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

int l;
int work(int o,char *O,int I)
{
    char c, *D=O ;
    if(o>0)
    {
        for(l=0;D[l];D[l++]-=10)
        {
            D[l++]-=120;
            D[l]-=110
; while(!work(0,O,l)) D[l]+=20; putchar((D[l]+1032)/20); } putchar(10); } else { c=o+(D[I]+82)%10-(I>l/2)*(D[I-l+I]+72)/10-9; D[I]+=I<0 ? 0 : !(o=work(c/10,O,I-1))*((c+999)%10-(D[I]+92)%10); } return o; } int main() { char
s[1200];s[0]='0'; scanf("%s",s+1); if(strlen(s)%2 == 1) work(2,s+1,0); else work(2,s,0); return 0; }