⭐【高精度加法】PAT A1136 A Delayed Palindrome

题目描述

在这里插入图片描述

知识点

STL使用

实现

码前思考

  1. 这道题目给我的第一感觉就是使用高精度整数运算,但是我想错了!后面看看柳神的代码

代码实现

//高精度整数运算
#include "bits/stdc++.h"
using namespace std;

const int maxn = 1e3+10;

struct bign{
	int d[maxn];
	int len;
	bign(){
		fill(d,d+maxn,0);
		len=0;
	}
}; 

string input;
int its;

bign rev(bign a){
	bign b;
	//开始逆反
	for(int i=a.len-1;i>=0;i--){
		b.d[b.len] = a.d[i];
		b.len++;
	}
	
	//去除前导0
	while(b.len > 1 && b.d[b.len-1] == 0){
		b.len--;
	} 
	 
	return b; 
}

//打印函数
void p(bign a){
	for(int i=a.len-1;i>=0;i--){
		printf("%d",a.d[i]);
	}
	return;
} 

bign sum(bign a,bign b){
	bign c;
	int carry = 0;
	for(int i=0;i<a.len||i<b.len;i++){
		int res = a.d[i]+b.d[i]+carry;
		c.d[c.len] = res%10;
		carry = res / 10;
		c.len++;
	}
	
	//查看是否还有进位
	while(carry!=0){
		c.d[c.len] = carry % 10;
		carry = carry / 10;
		c.len++;
	} 
	return c;
}

bool check(bign c){
	for(int i=0;i<=c.len/2;i++){
		if(c.d[i] != c.d[c.len-i-1]){
			return false;
		}
	}
	
	return true;
}

int main(){
	its = 0;
	cin>>input;
	//将字符串变成数字
	bign a;
	int len = input.size();
	for(int i=0;i<len;i++){
		int digit = input[len-i-1]-'0';
		a.d[a.len] = digit;
		a.len++; 
	} 
	
	if(check(a)){
		p(a);
		printf(" is a palindromic number.");
		return 0;
	}
	
	//接下来进行转化
	while(its<10){
		//得到逆反数组
		bign b = rev(a); 
		
		//进行相加
		bign c = sum(a,b); 
		
		p(a);
		printf(" + ");	
		p(b);	
		printf(" = ");
		p(c);
		printf("\n");
		
		if(check(c)){
			p(c);
			printf(" is a palindromic number.");
			return 0;
		}else{
			a = c;
		}
		its++;
	} 
	
	printf("Not found in 10 iterations.");
	
}

码后反思

  1. 上面的代码有几处不好的设计:
    1. 没有使用string,而是使用char[],其实这个题目用不上复杂的高精度整数运算,使用string即可;

    2. 没有使用自带的reverse()函数,而是自己去动手去写函数;数组可以直接用索引,容器得用begin()end() 在这里插入图片描述

    3. 可以直接使用string==操作符判断字符串相等。

  2. 柳神的代码:见解而高效
    #include <iostream>
    #include <algorithm>
    using namespace std;
    string rev(string s) {
        reverse(s.begin(), s.end());
        return s;
    }
    string add(string s1, string s2) {
        string s = s1;
        int carry = 0;
        for (int i = s1.size() - 1; i >= 0; i--) {
            s[i] = (s1[i] - '0' + s2[i] - '0' + carry) % 10 + '0';
            carry = (s1[i] - '0' + s2[i] - '0' + carry) / 10;
        }
        if (carry > 0) s = "1" + s;
        return s;
    }
    int main() {
        string s, sum;
        int n = 10;
        cin >> s;
        if (s == rev(s)) {
            cout << s << " is a palindromic number.\n";
            return 0;
        }
        while (n--) {
            sum = add(s, rev(s));
            cout << s << " + " << rev(s) << " = " << sum << endl;
            if (sum == rev(sum)) {
                cout << sum << " is a palindromic number.\n";
                return 0;
            }
            s = sum;
        }
        cout << "Not found in 10 iterations.\n";
        return 0;
    }
    
  3. 二刷之后发现自己之前的代码写错了:
    	//去除前导0
    	while(b.len > 1 && b.d[b.len-1] == 0){
    		b.len--;
    	} 
    
    是不需要去处前导0的!题目中的有出现前导0的情况!虽然能过题,只能说明PAT的测试用例不强!!!
    二刷代码:
    //使用高精度加法 
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <string>
    using namespace std;
     
    const int maxn = 1e4+10;	//内存开多大? 
    
    struct bign{
    	int data[maxn];
    	int len;
    	bign(){
    		fill(data,data+maxn,0);
    		len=0;
    	}	
    };
    
    bign str2bign(string& str){
    	int len = str.size();
    	bign a;
    	for(int i=0;i<len;i++){
    		int num = str[i]-'0';
    		a.data[len-1-i] = num;
    		a.len++;
    	}
    	return a;
    }
    
    bool check(bign a){
    	int len = a.len;
    	for(int i=0;i<=len/2;i++){
    		if(a.data[i] != a.data[len-1-i]){
    			return false;
    		}
    	}
    	return true;
    } 
    
    bign add(bign a,bign b){
    	int carry = 0;
    	bign c;
    	for(int i=0;i<a.len||i<b.len;i++){
    		int res = a.data[i]+b.data[i]+carry;
    		c.data[c.len] = res%10;
    		c.len++;
    		carry = res/10;
    	}
    	while(carry > 0){	//使用while循环!
    		c.data[c.len] = carry%10;
    		c.len++;
    		carry = carry/10;
    	}
    	return c;
    }
    
    void showNum(bign a){
    	int len = a.len;
    	for(int i=len-1;i>=0;i--){
    		printf("%d",a.data[i]);
    	}
    	return;
    }
    
    bign rev(bign a){
    	int len =a.len;
    	bign b=a;
    	reverse(b.data,b.data+len);	//直接用reverse
    	return b;
    }
    
    int main(){
    	string input;
    	cin>>input;
    	bign a;
    	a = str2bign(input);
    	bign b = rev(a);
    	bign c = a;
    	int t=10;
    	while(t>0 && !check(c)){
    		c = add(a,b);
    		showNum(a);
    		printf(" + ");
    		showNum(b);
    		printf(" = ");
    		showNum(c);
    		printf("\n");
    		a = c;
    		b = rev(a); 
    		t--;
    	}
    	if(check(c)){
    		showNum(c);
    		printf(" is a palindromic number.\n");
    	}else{
    		printf("Not found in 10 iterations.\n");
    	}
    	
    	//cout<<check(a);
    	return 0;
    } 
    
  4. 仿照柳神写的字符串实现大数加法:
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    string rev(string a){
    	string c = a;
    	reverse(c.begin(),c.end());
    	return c;
    }
    
    string add(string a,string b){
    	int carry = 0;
    	string c="";
    	for(int i=a.size()-1;i>=0;i--){
    		int res = a[i]-'0'+b[i]-'0'+carry;
    		c+=(res%10)+'0';
    		carry=res/10;
    	}
    	while(carry!=0){
    		c+=(carry%10)+'0';
    		carry = carry/10;
    	}
    	//需要倒转c
    	reverse(c.begin(),c.end()); 
    	return c;
    }
    
    int main(){
    	string a;
    	cin>>a;
    	string b=rev(a);
    	string c;
    	int t=10;
    	while(t > 0 && a!=b){
    		string c =  add(a,b);
    		cout<<a<<" + "<<b<<" = "<<c<<endl;
    		a = c;
    		b = rev(a);
    		t--;
    	} 
    	if(a==b){
    		cout<<a<<" is a palindromic number."<<endl;
    	}else{
    		cout<<"Not found in 10 iterations."<<endl;
    	}
    }
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值