iT邦幫忙

0

C++大數指數精度

  • 分享至 

  • xImage

Problem

給定一非負整數n計算2^n的值,一般而言把 2 乘上 n 次,就能得到答案。然而,當n特別大時,2^n要一次次地乘2可能稍嫌太慢,面對此一巨大問題利用分治(divide-and-conquer)演算法適當地拆解2 ^ n是個不錯的策略,特別是在進行2^m + 2^n這類運算時,其效果更為明顯。

Input

第一行是測資個數,接下來的每一行會有兩個非負整數m和n以一個空白鍵隔開,其中0 <= m+n <= 5555

Output

2^m + 2^n的精確值(每一筆輸出在十進制2,000位以內),每個case輸出完畢後請換行做為區隔。

Sample input

3
12 13
20 14
140 115

sample output

12288
1064960
1393796616446538814624603420284493227884544

我自己想的C++程式碼如下

#include <iostream>
#include <algorithm>
#include <cmath>
#include <iomanip>
using namespace std;

long double divide_and_conquer_big_exponent(long double exp);

int main()
{
    unsigned short T;
    long double m, n;

    cin >> T;
    for (unsigned short i = 0; i < T; ++i)
    {
        cin >> m >> n;
        // 2^m + 2^n = 2^min(m, n) * (2^abs(m-n) + 1)
        cout << setprecision(2000) << divide_and_conquer_big_exponent(min(m, n)) * (divide_and_conquer_big_exponent(abs(m - n)) + 1) << '\n';
    }
    return 0;
}

long double divide_and_conquer_big_exponent(long double exp)
{
    if (exp < 10)
    {
        return pow(2, exp);
    }
    return divide_and_conquer_big_exponent(exp / 2) * divide_and_conquer_big_exponent(exp - exp / 2);
}

但C++這樣寫精確度沒辦法到2000位,就連<cmath>裡面的pow()也沒辦法達到,因為pow()可以返回的最大精度類型是long double,這個也沒辦法到達2000位的精度。
想請問有其他方法可以用C++算到這麼高的精度嗎 ?? (像java裡面的BigInteger或python直接用**這樣可以直接計算大精度的整数)

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
一級屠豬士
iT邦新手 2 級 ‧ 2022-05-23 15:17:58
最佳解答

使用 GMP The GNU Multiple Precision Arithmetic Library
https://gmplib.org/
我很討厭這種先輸入幾組,然後再 xxx 空格 yyy 這樣的測試資料輸入方式.
只做最後一組.

#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

int main()
{
	mpz_t n,m,s;
	mpz_t base;
	
	mpz_init_set_ui(n,0);
	mpz_init_set_ui(m,0);
	mpz_init_set_ui(s,0);
  
    mpz_init_set_ui(base, 2);
   	
	mpz_pow_ui(n, base, 140);
	mpz_pow_ui(m, base, 115);
	mpz_add(s, n, m);
		
	printf("2 ^ 140 = ");
	mpz_out_str(stdout,10,n);
	printf("\n");
	
	printf("2 ^ 115 = ");
	mpz_out_str(stdout,10,m);
	printf("\n");
	
	printf("2 ^ 140 + 2 ^ 115 = ");
	mpz_out_str(stdout,10,s);
	printf("\n");
	
	mpz_clear(n);
	mpz_clear(m);
	mpz_clear(s);
	
	return EXIT_SUCCESS;
}

Result:

2 ^ 140 = 1393796574908163946345982392040522594123776
2 ^ 115 = 41538374868278621028243970633760768
2 ^ 140 + 2 ^ 115 = 1393796616446538814624603420284493227884544

我要發表回答

立即登入回答