《程序设计语言综合设计》第三周上机练习

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;
}
posted @ 2020-03-08 11:28  平和Kenn  阅读(885)  评论(0编辑  收藏  举报