個人思路僅供參考,如有不足歡迎交流。
傳送一個B(B≤16)進位制的數值N時,最後加上一個一位(B進位制的)校驗碼,使得N加上校驗位後能被B-1整除。比如十進制的數值12310,其校驗碼就是3,因爲十進制數值123310能被9整除。16進位制的數7816,其校驗碼爲0,因爲16進位制的78016是15的倍數。超過十進制後,用字母a表示10,字母b表示11,字母c表示12,字母d表示13,字母e表示14,字母f表示15。
告訴你進位制B,以及一個B進位制的正整數N,要求你計算正整數N在B進位制下的校驗碼。
輸入第一行正整數t (10 ≤ n ≤ 100),表示有多少組測試數據。
後面有t行,每行兩個正整數B,N(2≤ B≤16),中間用一個空格隔開,B是10進位制整數,N用B進位制形式表示。測試數據保證沒有非法的B進位制數N(也即N中每一位都是在0到B-1之間,沒有前導0)。
40%的測試數據N的位數L 1 ≤ L≤ 10;
30%的測試數據N的位數L 1 ≤ L≤ 10^2;
20%的測試數據N的位數L 1 ≤ L≤ 10^3;
10%的測試數據N的位數L 1 ≤ L≤ 10^4;
對於每組測試數據,輸出一位佔一行:正整數N在B進位制下的校驗碼。(如果校驗碼可以爲B-1,也可以爲0,輸出0)。
4
10 123
16 78
16 1234321
12 ab
3
0
e
1
第一行的4表示有4組測試數據,下面 下麪四行,每行一組測試數據。
第一組測試數據 10進位制數123 最後新增檢驗碼3,10進位制數1233是9(=10-1)的倍數
第二組測試數據 16進位制數78 最後新增檢驗碼0,16進位制數780是15(=16-1)的倍數
第三組測試數據 16進位制數1234321 最後新增檢驗碼e(=14),16進位制數1234321e是15(=16-1)的倍數
第四組測試數據 12進位制數ab 最後新增檢驗碼1,12進位制數ab1是11(12-1)的倍數
B進位制的數能被B-1整除,當且僅當各位數位和能被B-1整除。
第一組測試數據 10進位制數123 最後新增檢驗碼3,10進位制數1233各位數位和是9,是9的倍數
第二組測試數據 16進位制數78 最後新增檢驗碼0,16進位制數780各位數位和是15,是15的倍數
第三組測試數據 16進位制數1234321 最後新增檢驗碼e,16進位制數1234321e各位數位和是30,是15的倍數
第四組測試數據 12進位制數ab 最後新增檢驗碼1,12進位制數ab1各位數位和是22,是11的倍數
由於很多數據中數的長度明顯過長,所以採用了從頭到尾類似於豎式除法的方式來計算,類似於另一題「A除以B」。
提交程式碼如下(10/10分,C++):
//37.校驗碼
#include <iostream>
#include <string>
using namespace std;
bool check(string _num, int base)
{
int len = _num.length(); //加上校驗碼之後數的位數
int temp = 0, t_num = 0; //每次除法的被除數、當前位置的數位(t_num和r賦值爲0是爲了消除警告)
int r = 0; //最後的餘數
for (int i = 0; i < len; i++) //從高位開始,類似於用豎式做除法
{
switch (_num[i]) //爲當前位置數位賦值
{
case '0':
{
t_num = 0;
break;
}
case '1':
{
t_num = 1;
break;
}
case '2':
{
t_num = 2;
break;
}
case '3':
{
t_num = 3;
break;
}
case '4':
{
t_num = 4;
break;
}
case '5':
{
t_num = 5;
break;
}
case '6':
{
t_num = 6;
break;
}
case '7':
{
t_num = 7;
break;
}
case '8':
{
t_num = 8;
break;
}
case '9':
{
t_num = 9;
break;
}
case 'a':
{
t_num = 10;
break;
}
case 'b':
{
t_num = 11;
break;
}
case 'c':
{
t_num = 12;
break;
}
case 'd':
{
t_num = 13;
break;
}
case 'e':
{
t_num = 14;
break;
}
case 'f':
{
t_num = 15;
break;
}
default:
break;
}
temp = t_num + temp * base; //temp=本位數位+上一位數位*base
if (temp < base && i == 0) //_num的第一位<base,
continue;
else
{
r = temp % (base - 1); //餘數
temp = r; //本次計算的餘數繼承到下一次計算
}
}
if (r == 0) //最後餘數爲0,即能夠整除
{
cout << _num[len - 1] << endl; //輸出校驗碼
return true; //找到校驗碼
}
return false; //沒有找到校驗碼
}
int main()
{
int n; //測試數據有n組
int base; //base進位制
string num, _num; //輸入的數、加上校驗碼之後的數
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> base >> num;
for (int j = 0; j < base; j++) //校驗碼j從0到base-1
{
switch (j)
{
case 0:
{
_num = num + '0';
break;
}
case 1:
{
_num = num + '1';
break;
}
case 2:
{
_num = num + '2';
break;
}
case 3:
{
_num = num + '3';
break;
}
case 4:
{
_num = num + '4';
break;
}
case 5:
{
_num = num + '5';
break;
}
case 6:
{
_num = num + '6';
break;
}
case 7:
{
_num = num + '7';
break;
}
case 8:
{
_num = num + '8';
break;
}
case 9:
{
_num = num + '9';
break;
}
case 10:
{
_num = num + 'a';
break;
}
case 11:
{
_num = num + 'b';
break;
}
case 12:
{
_num = num + 'c';
break;
}
case 13:
{
_num = num + 'd';
break;
}
case 14:
{
_num = num + 'e';
break;
}
case 15:
{
_num = num + 'f';
break;
}
default:
break;
}
if (check(_num, base) == true) //獲取到校驗碼
{
break;
}
}
}
return 0;
}