1. 程式人生 > >L1-3 宇宙無敵加法器 - 令人激動的一道題目

L1-3 宇宙無敵加法器 - 令人激動的一道題目

工程 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 宇宙無敵加法器 - 令人激動的一道題目