1 solutions

  • 0
    @ 2024-8-28 18:50:56

    题面解释:塔子哥是一个喜欢数学的小学生,他在课余时间经常玩一些有趣的数学游戏。有一天,他收到了一个神秘的信件,信中写着一个包含阿拉伯数字、小数点和特殊字符的加法表达式。这些特殊字符包括 !@#,并且它们之间的加法运算规则如下:! + ! = 0! + @ = 13! + # = 4@ + @ = 7@ + # = 20# + # = 5。为了能够正确计算出这个表达式的结果并在三天内回信,塔子哥需要你的帮助。输入的第一行为一个整数 len,表示加法表达式的长度(1len10001 \leq len \leq 1000);第二行为一个长度为 len 的字符串,表示加法表达式。输出一个整数或小数 ans,表示表达式的运算结果,输出结果应忽略前导零和后导零,并且当小数点后面为0时只需要输出整数部分。

    题解

    这道题目要求我们模拟两个数的加法,其中数的形式包含阿拉伯数字、小数点及特殊字符(!@#)。由于这些特殊字符之间有特定的加法规则,我们需要根据这些规则进行处理。

    解决思路

    1. 解析输入:首先读取表达式长度和表达式字符串,找到加号 + 的位置,将表达式分为两个部分。
    2. 处理小数点:为了方便后续计算,我们确保两个数都有小数部分。如果没有小数部分,则在后面加上 .0
    3. 分离整数部分和小数部分:分别提取出整数部分和小数部分。
    4. 模拟加法
      • 小数部分加法:从小数部分开始逐位相加,并处理进位。
      • 整数部分加法:同样逐位相加,注意进位。
    5. 格式化输出:在输出结果时,去掉不必要的前导零和后导零,并根据规则决定是否输出小数点后面的零。

    代码分析

    这段代码实现了对包含阿拉伯数字、小数点和特殊字符(!@#)的加法表达式的模拟加法运算。主要步骤包括:

    1. 变量定义:使用了 n 来存储输入的表达式长度,s 用于存储加法表达式,t 用于追踪进位。

    2. 特殊字符加法规则get 函数处理特殊字符之间的加法运算,根据字符组合返回相应的结果。

    3. 小数部分加法suf_add 函数从小数部分逐位加法,调用 get 函数处理特殊字符,并在计算过程中管理进位。

    4. 整数部分加法pre_add 函数与小数部分类似,从整数部分进行逐位加法,并在结束后处理剩余的进位。

    5. 主函数逻辑:主函数读取输入,查找加号并分割字符串,确保每部分都有小数点,最后调用相应的加法函数计算结果,并格式化输出,去除多余的零。

    Python代码

    _ = input()  # 读取输入长度,实际未使用
    a, b = input().split('+')  # 读取加法表达式,分割成两个部分 a 和 b
    
    # 分割整数部分和小数部分
    if '.' in a:
        a_int, a_dec = a.split('.')  # 如果 a 中有小数点,分割为整数和小数部分
    else:
        a_int, a_dec = a, ''  # 如果没有小数点,小数部分为空
    
    if '.' in b:
        b_int, b_dec = b.split('.')  # 如果 b 中有小数点,分割为整数和小数部分
    else:
        b_int, b_dec = b, ''  # 如果没有小数点,小数部分为空
    
    # 分别对齐整数部分和小数部分
    if len(a_int) > len(b_int):
        # 如果 a 的整数部分较长,则在 b 的整数部分前补零
        b_int = '0' * (len(a_int) - len(b_int)) + b_int
    else:
        # 如果 b 的整数部分较长,则在 a 的整数部分前补零
        a_int = '0' * (len(b_int) - len(a_int)) + a_int
    
    # 对齐小数部分
    if len(a_dec) > len(b_dec):
        # 如果 a 的小数部分较长,则在 b 的小数部分后补零
        b_dec = b_dec + '0' * (len(a_dec) - len(b_dec))
    else:
        # 如果 b 的小数部分较长,则在 a 的小数部分后补零
        a_dec = a_dec + '0' * (len(b_dec) - len(a_dec))
    
    # 定义一位的加法运算函数, carry为进位
    def sym_add(x, y, carry):
        # 定义特殊字符的加法规则
        rule = {
            '!!': 0,
            '!@': 13, '@!': 13,
            '!#': 4, '#!': 4,
            '@@': 7, 
            '@#': 20, '#@': 20,
            '##': 5
        }
        
        if x in '!@#':  # 如果 x 是特殊字符
            s = str(rule[x+y] + carry)  # 根据规则计算加法结果
        else:
            s = str(int(x) + int(y) + carry)  # 否则直接进行数字加法
        
        # 如果结果只有一位,返回结果和进位0
        if len(s) == 1:
            return s, 0
        else:
            return s[1], int(s[0])  # 否则返回当前位和进位
    
    # 计算小数部分
    ans, carry = '', 0  # 初始化结果和进位
    for i in reversed(range(len(a_dec))):  # 从小数部分的最后一位开始计算
        res, carry = sym_add(a_dec[i], b_dec[i], carry)  # 进行加法运算
        ans = res + ans  # 结果前插入当前位
    
    # 添加小数点
    ans = '.' + ans  # 在结果前添加小数点
    
    # 计算整数部分
    for i in reversed(range(len(a_int))):  # 从整数部分的最后一位开始计算
        res, carry = sym_add(a_int[i], b_int[i], carry)  # 进行加法运算
        ans = res + ans  # 结果前插入当前位
    
    if carry != 0:  # 如果最后还有进位,添加到结果前面
        ans = str(carry) + ans
    
    # 去除前导0和后导0
    ans = ans.strip('0')  # 去除结果中的前导0
    
    # 有可能整数部分只有0, 去除前导0后就没有整数部分了, 因此要补一个0
    if ans[0] == '.':  # 如果结果以小数点开头
        ans = '0' + ans  # 在前面补零
    
    # 如果没有小数部分, 那么小数点也应该去掉
    if ans[-1] == '.':  # 如果结果以小数点结尾
        ans = ans[:-1]  # 去掉小数点
    
    print(ans)  # 输出最终结果
    
    

    Java

    import java.util.ArrayList;
    import java.util.Scanner;
    
    public class Main {
    
        public static ArrayList<Character> A = new ArrayList<>(), B = new ArrayList<>(), res = new ArrayList<>();
        public static ArrayList<Character> A1 = new ArrayList<>(), B1 = new ArrayList<>(), res1 = new ArrayList<>();
    
        static int flag = 0;
    
        public static void main(String[] args) {
            Scanner in = new Scanner(System.in);
            int n = in.nextInt();
            String s = in.next();
            String[] split = s.split("\\+");
            String a = split[0];
            String b = split[1];
            if(a.contains(".") && b.contains(".")){
                String[] sa = a.split("\\.");
                String[] sb = b.split("\\.");
                String s1 = sa[1].length() >= sb[1].length() ? sa[1] : sb[1];
                String s2 = sa[1].length() >= sb[1].length() ? sb[1] : sa[1];
                int x = s1.length()-s2.length();
                for(int i=1;i<=x;i++){
                    s2 = s2 + "0";
                }
                for (int i = s1.length()-1; i >= 0; i--){
                    A1.add(s1.charAt(i));
                    B1.add(s2.charAt(i));
                }
                add1();
                s1 = sa[0].length() >= sb[0].length() ? sa[0] : sb[0];
                s2 = sa[0].length() >= sb[0].length() ? sb[0] : sa[0];
                //这里就是反着装进list
                for (int i = s1.length()-1; i >= 0; i--) A.add(s1.charAt(i));
                for (int i = s2.length()-1; i >= 0; i--) B.add(s2.charAt(i));
                add();
            }else if(a.contains(".")){
                String[] sa = a.split("\\.");
                String s1 = sa[0].length() >= b.length() ? sa[0] : b;
                String s2 = sa[0].length() >= b.length() ? b : sa[0];
                //这里就是反着装进list
                for (int i = s1.length()-1; i >= 0; i--) A.add(s1.charAt(i));
                for (int i = s2.length()-1; i >= 0; i--) B.add(s2.charAt(i));
                add();
                for (int i = sa[1].length()-1; i >=0; i--) {
                    res1.add(sa[1].charAt(i));
                }
            }else if(b.contains(".")){
                String[] sa = b.split("\\.");
                String s1 = sa[0].length() >= a.length() ? sa[0] : a;
                String s2 = sa[0].length() >= a.length() ? a : sa[0];
                //这里就是反着装进list
                for (int i = s1.length()-1; i >= 0; i--) A.add(s1.charAt(i));
                for (int i = s2.length()-1; i >= 0; i--) B.add(s2.charAt(i));
                add();
                for (int i = sa[1].length()-1; i >=0; i--) {
                    res1.add(sa[1].charAt(i));
                }
            }else{
                for (int i = a.length()-1; i >= 0; i--) A.add(a.charAt(i));
                for (int i = b.length()-1; i >= 0; i--) B.add(b.charAt(i));
                add();
    
            }
    
            // 先算小数
            StringBuilder string = new StringBuilder();
    
            //因为是反着装进list的,输出就得从末尾开始输出,例如751->157
    //        for (int i = res.size()-1; i>=0; i--) System.out.print(res.get(i));
    //        System.out.print(".");
    //        for (int i = res1.size()-1; i>=0; i--) System.out.print(res1.get(i));
    
    
    
            for (int i = res.size()-1; i>=0; i--){
                string.append(res.get(i));
            }
            string.append('.');
            for (int i = res1.size()-1; i>=0; i--){
                string.append(res1.get(i));
            }
            while(string.charAt(string.length()-1)=='0'){
                string.deleteCharAt(string.length()-1);
            }
            if(string.charAt(string.length()-1)=='.')
                string.deleteCharAt(string.length()-1);
            while(string.charAt(0)=='0'&&string.length()>1){
                string.deleteCharAt(0);
            }
            System.out.println(string.toString());
    
        }
    
        //这里就是最基础的十进制加法,将A和B的当前位加在一起,需要进位就靠t/=10来判断进位
        public static void add() {
            //如果之前一位进位了,那么t就是1,没进位t就是0
            int t = flag;
            for (int i = 0; i < B.size(); i++) {
                char num1 = A.get(i);
                char num2 = B.get(i);
                if(num1>='0'&&num1<='9'&&num2>='0'&&num2<='9')t+=num2-'0'+num1-'0';
                else if(num1=='!'&&num2=='!')t=t;
                else if(num1=='!'&&num2=='@'||num1=='@'&&num2=='!')t+=13;
                else if(num1=='!'&&num2=='#'||num1=='#'&&num2=='!')t+=4;
                else if(num1=='@'&&num2=='#'||num1=='#'&&num2=='@')t+=20;
                else if(num1=='@'&&num2=='@')t+=7;
                else if(num1=='#'&&num2=='#')t+=5;
                res.add( (char)((t % 10) + '0') );
                t /= 10;
            }
            for (int i = B.size(); i < A.size(); i++) {
                int num= A.get(i);
                t = num - '0' + t;
                res.add((char)((t % 10) + '0'));
                t /= 10;
            }
            //特判,如果a和b长度一样且a的最高位加b的最高位进位的话,t还保留着进位信息,加到res就好
            if (t > 0) res.add((char)(t+'0'));
        }
        public static void add1() {
            //如果之前一位进位了,那么t就是1,没进位t就是0
            int t = 0;
            for (int i = 0; i < A1.size(); i++) {
                char num1 = A1.get(i);
                char num2 = B1.get(i);
                if(num1>='0'&&num1<='9'&&num2>='0'&&num2<='9')t+=num2-'0'+num1-'0';
                else if(num1=='!'&&num2=='!')t=t;
                else if(num1=='!'&&num2=='@'||num1=='@'&&num2=='!')t+=13;
                else if(num1=='!'&&num2=='#'||num1=='#'&&num2=='!')t+=4;
                else if(num1=='@'&&num2=='#'||num1=='#'&&num2=='@')t+=20;
                else if(num1=='@'&&num2=='@')t+=7;
                else if(num1=='#'&&num2=='#')t+=5;
                res1.add((char)((t % 10) + '0') );
                t /= 10;
            }
            //特判,如果a和b长度一样且a的最高位加b的最高位进位的话,t还保留着进位信息,加到res就好
            if (t > 0) flag = t;
        }
    }
    

    Cpp

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    
    #define x first
    #define y second
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int, int> pii;
    
    const int N = 1010;
    
    int n;              // 表达式的长度
    string s;          // 存储输入的加法表达式
    int t = 0;         // 全局变量,记录进位
    
    // 处理特殊字符的加法运算
    int get(char a, char b) {
        if (a == '!' && b == '!') return 0;
        else if (a == '!' && b == '@') return 13;
        else if (a == '!' && b == '#') return 4;
        else if (a == '@' && b == '@') return 7;
        else if (a == '@' && b == '#') return 20;
        else if (a == '#' && b == '#') return 5;
        return get(b, a);  // 如果找不到规则,调换字符顺序
    }
    
    // 小数部分加法
    string suf_add(string a, string b) {
        string res = ""; // 存储结果
        for (int i = max(a.size(), b.size()) - 1; ~i; i--) {
            char c = '0', d = '0'; // 默认字符为'0'
            if (i < (int)a.size()) c = a[i]; // 取出当前位
            if (i < (int)b.size()) d = b[i]; // 取出当前位
            
            // 判断是否是特殊字符并进行加法计算
            if (!isdigit(c) && !isdigit(d)) t += get(c, d);
            else t += c - '0' + d - '0'; // 阿拉伯数字相加
    
            res += to_string(t % 10); // 结果的当前位
            t /= 10; // 更新进位
        }
        reverse(res.begin(), res.end()); // 反转结果
        while (res.size() > 1 && res.back() == '0') res.pop_back(); // 去除末尾零
        return res;
    }
    
    // 整数部分加法
    string pre_add(string a, string b) {
        reverse(a.begin(), a.end()); // 反转字符串以便从低位开始加
        reverse(b.begin(), b.end());
        string res = "";
        for (int i = 0; i < (int)a.size() || i < (int)b.size(); i++) {
            char c = '0', d = '0';
            if (i < (int)a.size()) c = a[i]; // 取出当前位
            if (i < (int)b.size()) d = b[i]; // 取出当前位
            
            // 判断是否是特殊字符并进行加法计算
            if (!isdigit(c) && !isdigit(d)) t += get(c, d);
            else t += c - '0' + d - '0';
    
            res += to_string(t % 10); // 结果的当前位
            t /= 10; // 更新进位
        }
        // 处理最后的进位
        while (t) {
            res += to_string(t % 10);
            t /= 10;
        }
        while (res.size() > 1 && res.back() == '0') res.pop_back(); // 去除末尾零
        reverse(res.begin(), res.end()); // 反转回原来的顺序
        return res;
    }
    
    int main() {
        cin >> n >> s; // 输入长度和表达式
        int pos = s.find('+'); // 查找加号的位置
        string a = s.substr(0, pos), b = s.substr(pos + 1); // 分割成两部分
        if (a.find('.') == a.npos) a += ".0"; // 若没有小数点,加上.0
        if (b.find('.') == b.npos) b += ".0"; // 若没有小数点,加上.0
        int pos_a = a.find('.'), pos_b = b.find('.'); // 找到小数点的位置
        string pre_a = a.substr(0, pos_a), suf_a = a.substr(pos_a + 1); // 分离整数和小数部分
        string pre_b = b.substr(0, pos_b), suf_b = b.substr(pos_b + 1);
    
        // 先计算小数部分,再计算整数部分
        string suf_res = suf_add(suf_a, suf_b);
        string pre_res = pre_add(pre_a, pre_b);
        
        // 输出结果
        cout << pre_res;
        if (suf_res != "0") cout << '.' << suf_res; // 如果小数部分不为零,则输出
        return 0;
    }
    
    
    • 1

    2023.05.06-暑期实习-第二题-加法

    Information

    ID
    19
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    6
    Tags
    # Submissions
    189
    Accepted
    23
    Uploaded By