HDU.1002 A + B Problem II

原題

HDU.1002 A + B Problem II

分類

雜題·大位整數運算

題意

計算從任意兩個長度在1000以內的正整數的和。

輸入/輸出 要求與格式
輸入內容 最開始一行開始輸入樣例數,對每個樣例一行輸入兩個正整數(空格分開)
輸出結果 結果爲兩數和
輸出格式 每個案例結果第一行爲"Case X:",第二行爲計算結果,兩個案例結果間一個空行

題解

這道題說明了整數長度在1000以內,因此,一般的long long這種系統的整數類型是不夠的,我們必須得用字符串來操作。

計算的方法其實很簡單,就是我們小學算加法的時候用到的【豎式計算】。

雖然方法簡單,但是我們還是需要自己多舉幾個例子,從其中找到普遍的規律,再來編程。

多舉幾個例子,稍微總結一下,可以大概總結爲以下三種

  • 無進位,結果位數與加數的最大位數相同
  • 有進位,結果位數與加數的最大位數相同
  • 有進位,結果位數比加數的最大位數多1

如下圖所示
總結出三種豎式
那麼,我們需要考慮的也可以總結爲以下兩點:

  • 運算過程中的進位
  • 最終結果的位數

首先,我們構思一下輸入,我選擇的是string字符串(怎麼說畢竟是系統庫,有API呀)。

然後就是我們之前考慮的兩個問題了。

第一個問題——計算進位。運算的時候,我們會先對齊兩個加數相應的位(個位、十位、……)。對齊後,從最後一位(個位)開始對應數字相加得到一個數tmp,再將tmp/10的結果加到十位的計算中,然後最終結果的個位即爲tmp%10。以後的每一位都是類似的算法,循環解決問題,對於最高位只要稍微處理一下就可以了。

第二個問題——結果位數。這個很好辦,我們在計算前就先定義好一個string res用來存放結果,這個res就是兩個數中最長的再往前放一個前導0,這就涉及【字符串拼接】。當計算完最後結果時,如果最大爲爲0,說明計算時最高位沒有進位,我們可以就要把多餘的前導0抹去,這就涉及【字符串截取】

(例如:12 + 999,我們就可以先暫定string res = "0999",有人也許會覺得應該設置爲string res = "0000",但是實際上沒有必要,因爲每一位計算的結果都會不斷刷新res,res的初始值根本不重要,只有其最大可能位數是最重要的)

操作 示例代碼 解釋
字符串拼接 string a = "0", b = "1", c = a + b; 將a在前b在後拼接成一個新字符串c
截取子串 string res = c.substr(1); 將字符串c從下標1開始(包括)截取到末尾生成一個型字符串res

題解代碼

HDU(C++/G++)AC代碼如下:

#include <iostream>
#include <algorithm>
#include <string>

using namespace std;

int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	int T;
	string a, b;
	string at, bt;
	int cnt = 1;
	//接收樣例數
	cin >> T;
	while (T--)
	{
		//接收數據
		cin >> a >> b;
		at = a;
		bt = b;
		//長度處理——長的在上
		if (a.length() < b.length())
			swap(a, b);
		//數據準備
		int len_min = b.length();
		int len_max = a.length();
		string res = "0";
		res += a;
		int add_once;
		int add_next = 0;
		//開始計算
		while (max(len_min, len_max) >= 0)
		{
			--len_min;
			--len_max;
			if (len_min > -1)
				add_once = a[len_max] + b[len_min] - 96 + add_next;
			else
			{
				if (len_max > -1)
					add_once = a[len_max] - 48 + add_next;
				else
					add_once = add_next;
			}
			add_next = add_once / 10;
			res[len_max + 1] = add_once % 10 + 48;
		}
		//去除前導0
		if (res[0] == '0')
			res = res.substr(1);
		//打印結果
		cout << "Case " << cnt << ':' << endl;
		cout << at << " + " << bt << " = " << res << endl;
		if (T)
			cout << endl;
		++cnt;
	}

	return 0;
}

評價

這道題應該算是一道模板題,大位整數的四則運算,應對這種題,最好還是寫成一套靠譜的模板好一些。

補充

這道題在C++裏雖然·是道模板題,但是在Java裏卻可以說和HDU.1000 A + B Problem幾乎是一個難度級別的,因爲Java中系統裏的包就有BigInteger大數類,很容易操作,有興趣的話可以去稍微瞭解一下。

後話

寫這題的題解的時候,雖然覺得寫得勉強還算詳細,但是總覺得不太對勁,可能是有些段落文字太多,顯得亂七八糟😅😅😅,亦或是因爲有些小的細枝末節的地方沒有詳細講解如何處理(比如較短的字符串如何處理、兩個結果間一個空行格式如何控制)其實代碼裏都有,但是我覺得都拋出來放到題解裏會更亂,所以就沒加。有好的建議評論區提提,謝謝。

發佈了4 篇原創文章 · 獲贊 4 · 訪問量 301
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章