L1-3 宇宙無敵加法器 - 令人激動的一道題目
阿新 • • 發佈:2018-03-25
工程 add tac bre 輸出 c++ IT mes 進位
L1-3 宇宙無敵加法器 - 令人激動的一道題目
感覺好久沒有這麽認真的做一道題了,今天看到一句話,
說是編程是一個工程型的工作,想要學好,”無他,唯手熟爾“
之前覺得自己笨,懷疑自己,但是自己還沒有投入時間,精力去做這件事,就要一下子做好,這就是在做夢
在ACM隊呆了很長時間了,感覺自己沒有取得什麽成就,
其實還是沒有自己主動地去用大量的時間題目去磨練自己,
最近在做PAT上的題目,感覺這上邊的題目是不難,但是想要全部做對還是很難的。
題目
地球人習慣使用十進制數,並且默認一個數字的每一位都是十進制的。而在PAT星人開掛的世界裏,每個數字的每一位都是不同進制的,這種神奇的數字稱為“PAT數”。每個PAT星人都必須熟記各位數字的進制表,例如“……0527”就表示最低位是7進制數、第2位是2進制數、第3位是5進制數、第4位是10進制數,等等。每一位的進制d或者是0(表示十進制)、或者是[2,9]區間內的整數。理論上這個進制表應該包含無窮多位數字,但從實際應用出發,PAT星人通常只需要記住前20位就夠用了,以後各位默認為10進制。
在這樣的數字系統中,即使是簡單的加法運算也變得不簡單。例如對應進制表“0527”,該如何計算“6203+415”呢?我們得首先計算最低位:3+5=8;因為最低位是7進制的,所以我們得到1和1個進位。第2位是:0+1+1(進位)=2;因為此位是2進制的,所以我們得到0和1個進位。第3位是:2+4+1(進位)=7;因為此位是5進制的,所以我們得到2和1個進位。第4位是:6+1(進位)=7;因為此位是10進制的,所以我們就得到7。最後我們得到:6203+415=7201。
輸入格式:
輸入首先在第一行給出一個N位的進制表(0 < N <=20),以回車結束。 隨後兩行,每行給出一個不超過N位的非負的PAT數。
輸出格式:
在一行中輸出兩個PAT數之和。
輸入樣例:
30527
06203
415
輸出樣例:
7201
ps: 之前做過大數相加這類的題目,自己寫是能寫出來的,但是需要調整好長時間,因此學習了粉書上的大數相加以後就覺得還是書上那種方法更好,更結構化
做題曲折歷程
看到就是大數相加類型的,只不過不是10進制,而是指定進制的一道題,其實做了大數相加以後,這類的題應該就沒有什麽問題了。但是實際做的過程中還是遇到很多困難。
- 數的讀入處理,由於有前導0,導致問題不太好解決,之前看過用stringstream來解決數與字符的轉化問題,所以就采用了這種方法,但其實是有局限的,因為如果這個字符串太長比如20,那麽就導致溢出問題
- 字符串翻轉問題,一開始以為是stringstream的問題,後來才發現是字符串翻轉的時候出現了問題,應該用 i < len/2 而不能用 i <= len/2 來做
- 最後註意在提交的時候要把freopen去掉
代碼
//L1-3
#include <bits/stdc++.h>
using namespace std;
string add1,add2;
string pattern;
void reverse(){
int len = add1.length();
for(int i = 0 ; i < len/2; i++){
char tmp = add1[i];
add1[i] = add1[len-1-i];
add1[len-i-1] = tmp;
}
len = add2.length();
for(int i = 0 ; i < len/2; i++){
char tmp = add2[i];
add2[i] = add2[len-1-i];
add2[len-i-1] = tmp;
}
len = pattern.length();
for(int i = 0 ; i < len/2; i++){
char tmp = pattern[i];
pattern[i] = pattern[len-1-i];
pattern[len-i-1] = tmp;
}
}
int main()
{
freopen("in.txt","r",stdin);
stringstream ss1,ss2,ss3;
long long a,b,c;
cin >> a >> b >> c;
// cout << a << endl;
// cout << b << endl;
// cout << c << endl;
ss1 << a;
ss1 >> pattern;
ss2 << b;
ss2 >> add1;
ss3 << c;
ss3 >> add2;
// cout << pattern << endl;
// cout << add1 << endl;
// cout << add2 << endl;
// cout << pattern.length() << add1.length() << add2.length()<< endl;
// cin >> pattern >> add1 >> add2;
// cout << pattern.length() << add1.length() << add2.length()<< endl;
reverse();
int len1 = add1.length();
int len2 = add2.length();
// cout << pattern << endl;
// cout << add1 << endl;
// cout << add2 << endl;
vector<int>ans;
for(int i=0, g=0; ; i++){
if(g == 0 && i >= len1 && i >= len2)break;
int x = g;
if(i < len1) x += add1[i]-'0';
if(i < len2) x += add2[i]-'0';
int test = (int)(pattern[i]-'0');
if(i <= 20 && test != 0){
ans.push_back(x % test);
g = x/test;
// cout << "tag1" << endl;
}
else
{
ans.push_back(x % 10);
g = x/10;
}
}
for(int i = ans.size()-1; i >= 0 ; i--)
cout << ans[i];
cout << endl;
return 0;
}
- 這道題讓我調試了很長時間,最後結果還是有兩個測試點沒有通過,原因也很簡單,即便是采用long long,讀20位以上的還是不可行的
- 但是這個題讓我學到了很多,只要多練多記還是可以的。
下邊代碼
這個代碼采用的是用棧來解決大數相加的問題,相比這個更加靈活
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
void inputTostack(stack<int> &stk)
{
char k;
while((k=cin.get())!='\n')
stk.push(k-'0');
}
int retTop(stack<int> &stk)
{
int k=stk.top();
stk.pop();
return k;
}
int main()
{
stack<int> stk,n1,n2,ans;
inputTostack(stk);
inputTostack(n1);
inputTostack(n2);
int add=0;
while(!n1.empty()&&!n2.empty())
{
int sum=retTop(n1)+retTop(n2)+add,d=retTop(stk);
if(!d) d+=10;
ans.push(sum%d);
add=sum/d;
}
while(!n1.empty())
{
int sum=retTop(n1)+add,d=retTop(stk);
if(!d) d+=10;
ans.push(sum%d);
add=sum/d;
}
while(!n2.empty())
{
int sum=retTop(n2)+add,d=retTop(stk);
if(!d) d+=10;
ans.push(sum%d);
add=sum/d;
}
ans.push(add);
while(ans.size()>1&&ans.top()==0)
ans.pop();
while(!ans.empty())
{
cout<<ans.top();
ans.pop();
}
return 0;
}
L1-3 宇宙無敵加法器 - 令人激動的一道題目