《程序設計語言綜合設計》第三周上機練習


4 回文數

對於一個自然數n,若將n的各位數字反向排列所得的數n1與n相等,則稱n為回文數,例如2332。
若給定一個N( 2<=N<=16)進制數M(M的長度在一百位以內),如果M不是回文數,可以對其進行N進制加法,最終得到回文數。
例如對於十進制數79 STEP1 : 79 + 97 = 176 STEP2 : 176 + 671 = 847 STEP3 : 847 + 748 = 1595 STEP4 : 1595 +5951 = 7546 STEP5 : 7546 + 6457 = 14003 STEP6 : 14003 + 30041 = 44044
那么對於給定的N進制數M,請判斷其能否在30步以內(包括30步)得到回文數。

輸入格式

第一行包括一個正整數 N(2<=N<=16)。
第二行包括一個正整數M(一百位以內)。

輸出格式

如果可以在n步內得到回文數,輸出“STEP=n”,否則輸出“NO”。

輸入樣例1

10
79

輸出樣例1

STEP=6

輸入樣例2

8
665556

輸出樣例2

NO

Accepted

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
void rever(string a){ //可用 reverse(a.begin(), a.end());代替
    int i,j;
    char temp;
    int len=(int)a.size()-1;
    if(len%2){
    for(i=0,j=len-1;i!=j;i++,j--){
        temp=a[i];
        a[i]=a[j];
       a[j]=temp;
      }
    }
    if(len%2==0){
    for(i=0,j=len-1;i!=j-1;i++,j--){
        temp=a[i];
        a[i]=a[j];
       a[j]=temp;
      }
    }
}
string sum_str(string m,int n){
    int temp = 0,i;
    int flag=0;
    string a;
    int j=(int)m.size()-1;
    for(i=0;i<m.size()&&j>=0;i++,j--){
        temp=0;
       if(m[i]>='0'&&m[i]<='9') temp+=(m[i]-'0');
        if(m[j]>='0'&&m[j]<='9') temp+=(m[j]-'0');
        if(m[i]>='A'&&m[i]<='Z')temp+=(m[i]-'A')+10;
        if(m[j]>='A'&&m[j]<='Z')temp+=(m[j]-'A')+10;
        if(flag==1){//進位1
            temp++;
             flag=0;
        }
        if(temp>=n){//大於n要進位
            flag=1;
            temp-=n;}
        if(temp<10) temp+='0';
        else temp=temp-10+'A';
          a+=temp;
    }
    if(flag==1){
        a=a+"1";
    }
      rever(a);
    return a;
}
int judge(string m){
    int i,j;
    for(i=0,j=(int)m.size()-1;i<m.size()&&j>=0;i++,j--){
        if(m[i]!=m[j]) return 0;
    }
    return 1;
}
int main() {
    int n;
    int step=0;
    string m;
    cin >> n;
    cin >> m;
    if(judge(m)) cout << "STEP=" <<step << endl;
    else{
        while(step<=30){
            m=sum_str(m,n);
            step++;
            
            if(judge(m)){
                cout << "STEP=" <<step << endl;
                break;
            }
        }
    }
    if(step>30) {cout << "NO" << endl; }
    return 0;
}

高精度計算加減乘除

5 數樓梯

樓梯有N階,上樓可以一步上一階,也可以一步上兩階。那么走到第N階樓梯共有多少種不同的走法呢?

輸入格式

一個正整數 N(1<=N<=5000),表示樓梯階數。

輸出格式

輸出一個數,表示走到第N階樓梯有多少種走法。
注意,數據范圍很大,即使是64位也可能不夠存。

輸入樣例1

4

輸出樣例1

5

輸入樣例2

400

輸出樣例2

28481229810848961175798893768146099561538008878230489098647719564596927140403

Accepted
(來源:洛谷)

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int len=1,fl[5005][5005]={0};//fl[k][i]--第k階台階所對應的走法數
void floor(int k){
    int i;
    for(i=1;i<=len;i++)
        fl[k][i]=fl[k-1][i]+fl[k-2][i];
    for(i=1;i<=len;i++){
        if(fl[k][i]>=10){
            fl[k][i+1]+=fl[k][i]/10;
            fl[k][i]=fl[k][i]%10;
            if(fl[k][len+1]) len++;
        }
    }
}
int main() {
    int n;
    cin >> n;
    fl[1][1]=1;
    fl[2][1]=2;
    for(int i=3;i<=n;i++){
        floor(i);
    }
    for(int i=len;i>=1;i--){
        printf("%d",fl[n][i]);
    }
    return 0;
}

這道題我們可以論述一下遞推與遞歸的方法與區別

遞推一般用循環來解決,從已知條件到未知逐漸接近結果:
(1)將復雜運算分解為若干重復的簡單運算
(2)后一步驟建立在前一步驟之上
(3)計算每一步驟的方法相同
(4)從開始向后計算出結果
(5)使用循環結構,通過多次循環逐漸逼近結果
遞歸一般自己調用自己,從未知到已知,把規模大的、較難解決的問題變成規模較小的、易解決的同一問題。規模較小的問題又變成規模更小的問題,並且小到一定程度可以直接得出它的解,從而得到原來問題的解。
(1)每一次遞歸都縮小問題規模,直到問題足夠小
(2)使用選擇分支語句
(3)從后往開始逐步逼近
(4)達到最開始,再把初始值帶入往后逐一求解

6 A-B

已知兩個數A和B,求A-B的運算結果。

輸入格式

輸入包括兩個正整數A和B 。(0<A,B≤1e10086)

輸出格式

輸出A-B的運算結果。

輸入樣例1

3
2

輸出樣例1

在這里給出相應的輸出。例如:
1

輸入樣例2

11102356985410
2356985410235698

輸出樣例2

在這里給出相應的輸出。例如:
-2345883053250288

Wrong Answer

給出我的比較麻煩的代碼(只有90分,待修改)

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int sign=0;
string sub(string a,string b){
    string ans;
    int temp;
    long  long lena=(int)a.size();
    long long lenb=(int)b.size();
     reverse(a.begin(), a.end());
     reverse(b.begin(), b.end());
    long long i;
    int flag=0;
    if(lena<lenb){
        sign=1;
        for(i=0;i<lenb;i++){
            int at=0,bt=0;
            if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
            if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
           temp=bt-at;
            if(flag==1) {
                temp--;
                flag=0;
            }
            if(temp<0){
                temp+=10;
                flag=1;
            }
            ans+=temp+'0';
        }
        // if(temp<0) sign=1;
    }
    if(lena==lenb){
         if(a<b)  sign=1;
        if(sign){
        for(i=0;i<lenb;i++){
            int at=0,bt=0;
            if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
            if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
            temp=bt-at;
            if(flag==1) {
                temp--;
                flag=0;
            }
            if(temp<0){
                temp+=10;
                flag=1;
            }
            ans+=temp+'0';
        }
              // if(temp<0) sign=1;
        }
        else{
            for(i=0;i<lena;i++){
                int at=0,bt=0;
                if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
                if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
                 temp=at-bt;
                if(flag==1) {
                    temp--;
                    flag=0;
                }
                if(temp<0){
                    temp+=10;
                    flag=1;
                }
                ans+=temp+'0';
            }
            //if(temp<0) sign=1;
        }
    }
    if(lena>lenb){
           for(i=0;i<lena;i++){
               int at=0,bt=0;
               if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
               if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
              temp=at-bt;
               if(flag==1) {
                   temp--;
                   flag=0;
               }
               if(temp<0){
                   temp+=10;
                   flag=1;
               }
               ans+=temp+'0';
           }
       //  if(temp<0) sign=1;
       }
    reverse(ans.begin(), ans.end());
    return ans;
}
int main() {
    string a,b;
    string ans;
    int flag=0;
    cin >> a;
    getchar();
    cin >> b;
    getchar();
    if(a==b) {
        cout << "0" << endl;
        return 0;
    }
    ans=sub(a,b);
    if(sign) cout <<"-";
    for(long long i=0;i<ans.size();i++){
        if(flag==0&&ans[i]!='0'){
            cout << ans[i];
            flag=1;
        }
        else if(flag==1){
            cout << ans[i];
        }
    }
    return 0;
}

后來詢問發現,第一版錯的原因在於當兩個數長度不相等時,未對數字進行相應的初始化。
更改后終於AC:

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int sign=0;
string sub(string a,string b){
    string ans;
    int lena=(int)a.size();
    int lenb=(int)b.size();
     reverse(a.begin(), a.end());
     reverse(b.begin(), b.end());
    int i;
    int flag=0;
    if(lena<lenb){
        sign=1;
        for(i=lena;i<lenb;i++){
                   a+='\0';
               }
        for(i=0;i<lenb;i++){
            int at=0,bt=0;
            if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
            if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
            int temp=bt-at;
            if(flag==1) {
                temp--;
                flag=0;
            }
            if(temp<0){
                temp+=10;
                flag=1;
            }
            ans+=temp+'0';
        }
    }
    if(lena==lenb){
         if(a<b)  sign=1;
        if(sign){
        for(i=0;i<lenb;i++){
            int at=0,bt=0;
            if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
            if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
            int temp=bt-at;
            if(flag==1) {
                temp--;
                flag=0;
            }
            if(temp<0){
                temp+=10;
                flag=1;
            }
            ans+=temp+'0';
        }}
        else{
            for(i=0;i<lena;i++){
                int at=0,bt=0;
                if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
                if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
                int temp=at-bt;
                if(flag==1) {
                    temp--;
                    flag=0;
                }
                if(temp<0){
                    temp+=10;
                    flag=1;
                }
                ans+=temp+'0';
            }
        }
    }
    if(lena>lenb){
        for(i=lenb;i<lena;i++){
            b+=' ';
        }
           for(i=0;i<lena;i++){
               int at=0,bt=0;
               if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
               if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
               int temp=at-bt;
               if(flag==1) {
                   temp--;
                   flag=0;
               }
               if(temp<0){
                   temp+=10;
                   flag=1;
               }
               ans+=temp+'0';
           }
       }
    reverse(ans.begin(), ans.end());
    return ans;
}
int main() {
    string a={0},b={0};
    string ans;
    int flag=0;
    cin >> a;
    getchar();
    cin >> b;
   // getchar();
    if(a==b) {
        cout << "0" << endl;
        return 0;
    }
    ans=sub(a,b);
    if(sign) cout <<"-";
    for(int i=0;i<ans.size();i++){
        if(flag==0&&ans[i]!='0'){
            cout << ans[i];
            flag=1;
        }
        else if(flag==1){
            cout << ans[i];
        }
    }
    return 0;
}

Accepted
(來源:大數減法)

第二版更加簡練,把判斷的部分放在main函數中,且AC了

#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
string sub(string a,string b,int len){
    int i;
    string ans;
    int lenb=(int)b.size();
    for(i=0;i<lenb;i++){
        if(a[i]>=b[i]){ //不需要向前借1
            ans+=a[i]-b[i]+'0';
        }
        else{//需要向前借1
            ans+=a[i]+10-b[i]+'0';
            a[i+1]--;
        }
    }
    for(;i<len;i++){
        ans+=a[i];
    }
      reverse(ans.begin(), ans.end());
    return ans;
}
int main() {
    string a,b;
    string ans;
    int i;
    int flag=0;
    cin >> a >> b;
    reverse(a.begin(), a.end());
    reverse(b.begin(), b.end());
    int lena=(int)a.size();
    int lenb=(int)b.size();
    if(lena>lenb){ ////若減數長度 > 被減數長度,正常減
        ans=sub(a,b,lena);
        for(i=0;i<ans.size();i++){
            if(flag==0&&ans[i]>'0'&&ans[i]<='9')   {
                cout << ans[i];
                flag=1;
            }
            else if(flag==1) cout << ans[i];
        }
        return 0;
    }
    else if(lena<lenb){//若減數長度 < 被減數長度,被減數-減數
        cout <<"-";
        ans=sub(b,a,lenb);
        for(i=0;i<ans.size();i++){
                    if(flag==0&&ans[i]>'0'&&ans[i]<='9')   {
                                 cout << ans[i];
                                 flag=1;
                             }
                   else if(flag==1) cout << ans[i];
               }
        return 0;
    }
    else{//若減數長度 == 被減數,判斷兩個數的大小
        
        if(a>b){
            ans=sub(a,b,lena);
             for(i=0;i<ans.size();i++){
                         if(flag==0&&ans[i]>'0'&&ans[i]<='9')   {
                                     cout << ans[i];
                                     flag=1;
                                 }
                       else if(flag==1) cout << ans[i];
                   }
        }
        else if(a<b){
            cout <<"-";
            ans=sub(b,a,lenb);
             for(i=0;i<ans.size();i++){
                         if(flag==0&&ans[i]>'0'&&ans[i]<='9')   {
                                     cout << ans[i];
                                     flag=1;
                                 }
                       else if(flag==1) cout << ans[i];
                   }
        }
        else{
            cout << "0" << endl;
        }
    }
    return 0;
}

7 高精度除法

給兩個正整數 a,b,求 a/b的整數部分。

輸入格式

輸入共兩行,每行一個正整數,分別表示 a和b。 50%數據,a,b均小於1e18, 50%數據,a,b均小於1e500。

輸出格式

輸出一個整數,表示a/b的整數部分。

輸入樣例1

3
2

輸出樣例1

1

輸入樣例

24781236498237462378425347823652387423654238752372365327862
8934457724628746

輸出樣例2

2773669903874014740488146558678531750078864

Accepted
(來源:大數除法)

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int L=11000;
int sub(int *a,int *b,int lena,int lenb)
{
    if(lena<lenb) return -1;//如果a小於b,則返回-1
    if(lena==lenb)
    {
        for(int i=lena-1;i>=0;i--)
            if(a[i]>b[i]) break;
            else if(a[i]<b[i]) return -1;//如果a小於b,則返回-1
 
    }
    for(int i=0;i<lena;i++)//高精度減法
    {
        a[i]-=b[i];
        if(a[i]<0) {a[i]+=10;a[i+1]--;}
    }
    for(int i=lena-1;i>=0;i--)
        if(a[i]) return i+1;//返回差的位數
    return 0;//返回差的位數
 
}
string div(string n1,string n2)//n1,n2是字符串表示的被除數
{
    string s,v;//s存商,v存余數
    int a[L]={0},b[L]={0},r[L]={0},lena=n1.size(),lenb=n2.size(),i;//a,b是整形數組表示被除數,除數
     for(i=lena-1;i>=0;i--) a[lena-1-i]=n1[i]-'0';
     for(i=lenb-1;i>=0;i--) b[lenb-1-i]=n2[i]-'0';
     if(lena<lenb || (lena==lenb && n1<n2)) {
     return "0";
     }//如果a<b,則商為0
     int t=lena-lenb;//除被數和除數的位數之差
     for(int i=lena-1;i>=0;i--)//將除數擴大10^t倍
        if(i>=t) b[i]=b[i-t];
        else b[i]=0;
     lenb=lena;
     for(int j=0;j<=t;j++)
     {
         int temp;
         while((temp=sub(a,b+j,lena,lenb-j))>=0)//如果被除數比除數大繼續減
         {
             lena=temp;
             r[t-j]++;
         }
     }
    for(i=0;i<L-10;i++) {r[i+1]+=r[i]/10;r[i]%=10;}//統一處理進位 ??
     while(!r[i]) i--;//將整形數組表示的商轉化成字符串表示的
     while(i>=0) s+=r[i--]+'0';
     return s;
     
}
int main()
{
    string a,b;
    cin>>a>>b;
    cout<<div(a,b)<<endl;
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM