PTA:运用顺序表实现多项式相加

本题要求输入两个一元多项式,然后输出它们的和(相加后得到的一元多项式)

输入格式:

输入一个整数n(表示输入组数),然后依次输入每一组数据:

输入一个整数A(表示多项式的项数,小于100),然后输入A对整数,每一对整数表示对应项的指数和系数。

输出格式:

对每一组输入,在一行中输出得到的一元多项式。

输入样例:

在这里给出一组输入。例如:

2
5
0 2
1 4
5 7
7 10
8 19
4
0 3
2 6
4 19
5 -9
3
0 3
4 7
8 2
3
0 -3
5 9
7 21

输出样例:

在这里给出相应的输出。例如:

5x^0+4x^1+6x^2+19x^4-2x^5+10x^7+19x^8
7x^4+9x^5+21x^7+2x^8

方法思路

  1. 输入处理:读取输入数据,包括多项式的项数及其对应的指数和系数。
  2. 存储多项式:使用数组来存储每个指数对应的系数,数组下标表示指数,数组的值表示对应项的系数。
  3. 合并多项式:将两个多项式的对应项系数相加,存储到结果数组中。
  4. 格式化输出:遍历结果数组,按指数升序输出所有非零项。特别注意处理系数为1或-1的情况,以及符号和格式的正确显示。

代码

#include <stdio.h>   // 输入输出库

#define MAX_EXP 10000 // 定义多项式指数的最大值

int main() {
    int n;  // 测试用例数量
    scanf("%d", &n); // 读取测试用例数
    
    // 处理每个测试用例
    while (n--) {
        // 结果数组:索引代表指数,值存储对应系数(初始化为0)
        int result[MAX_EXP + 1] = {0};
        int A, B; // 两个多项式的项数
        
        /* 处理第一个多项式 */
        scanf("%d", &A); // 读取第一个多项式的项数
        for (int i = 0; i < A; i++) {
            int exp, coeff;
            scanf("%d %d", &exp, &coeff); // 读取指数和系数
            result[exp] += coeff; // 累加到对应指数位置
        }
        
        /* 处理第二个多项式 */
        scanf("%d", &B); // 读取第二个多项式的项数
        for (int i = 0; i < B; i++) {
            int exp, coeff;
            scanf("%d %d", &exp, &coeff);
            result[exp] += coeff; // 累加到对应指数位置
        }
        
        /* 输出合并后的多项式 */
        int is_first = 1;  // 标记是否是首项(用于处理符号)
        for (int exp = 0; exp <= MAX_EXP; exp++) { // 从低到高遍历所有指数
            int coeff = result[exp];
            if (coeff == 0) continue; // 跳过系数为0的项
            
            char sign = '\0';       // 符号字符(默认为空)
            int abs_coeff;          // 系数的绝对值
            
            // 符号处理逻辑
            if (is_first) {         // 处理首项
                if (coeff < 0) {    // 负数需要显示负号
                    sign = '-';
                    abs_coeff = -coeff;
                } else {            // 正数不显示符号
                    abs_coeff = coeff;
                }
                is_first = 0;       // 后续项不再为首项
            } else {                // 处理非首项
                if (coeff < 0) {    // 负数显示负号
                    sign = '-';
                    abs_coeff = -coeff;
                } else {            // 正数显示加号
                    sign = '+';
                    abs_coeff = coeff;
                }
            }
            
            // 输出符号(非首项或负数首项才有符号)
            if (sign != '\0') {
                putchar(sign);
            }
            
            // 输出项内容
            if (exp == 0) { // 处理常数项
                printf("%dx^0", abs_coeff); // 指数0的特殊格式
            } else {
                if (abs_coeff == 1) { // 系数1省略显示
                    printf("x^%d", exp);
                } else {
                    printf("%dx^%d", abs_coeff, exp);
                }
            }
        }
        
        // 处理所有项系数均为0的特殊情况
        if (is_first) { // 若从未输出过项,说明结果全为0
            printf("0");
        }
        printf("\n"); // 换行分隔不同测试用例
    }
    
    return 0; // 程序正常退出
}

代码解释

  1. 输入处理 :首先读取测试数据的组数 n。对于每组数据,分别读取两个多项式的项数及其对应的指数和系数,并将这些系数累加到结果数组中。
  2. 合并多项式:通过遍历两个多项式,将对应指数的系数相加,存储在结果数组中。
  3. 输出结果:遍历结果数组,按指数升序输出所有非零项。处理每个项的符号和格式,确保正确显示系数为1或-1的情况,以及首项的符号处理。
  4. 特殊情况处理:如果所有项的系数均为0,则输出0。

以下是该C语言程序的详细分步解释:


1. 程序框架与输入处理

c复制代码

#include <stdio.h>
#include <string.h>

#define MAX_EXP 10000 

int main() {
    int n;
    scanf("%d", &n); // 读取测试组数
    while (n--) {    // 处理每组测试数据
        int result[MAX_EXP + 1] = {0}; // 初始化结果数组为0
        int A, B;

        // 处理第一个多项式
        scanf("%d", &A);
        for (int i = 0; i < A; i++) {
            int exp, coeff;
            scanf("%d %d", &exp, &coeff);
            result[exp] += coeff; // 累加系数到对应指数
        }

        // 处理第二个多项式(逻辑同上)
        scanf("%d", &B);
        for (int i = 0; i < B; i++) {
            int exp, coeff;
            scanf("%d %d", &exp, &coeff);
            result[exp] += coeff;
        }

        // ...后续输出逻辑...
    }
    return 0;
}
关键点:
  • 数组存储多项式 :使用result数组存储合并后的多项式,数组索引为指数(如result[5]表示指数为5的项的系数)。
  • 累加系数:两个多项式的相同指数项系数直接相加,若和为0则该指数项消失。
  • 假设指数范围MAX_EXP设为10000,若输入指数超过此值会越界(题目未明确限制,需根据题意调整)。

2. 输出格式化逻辑

c复制代码

int is_first = 1; // 标记是否是首项
for (int exp = 0; exp <= MAX_EXP; exp++) {
    int coeff = result[exp];
    if (coeff == 0) continue; // 跳过系数为0的项

    char sign = '\0';
    int abs_coeff;
    // 处理符号
    if (is_first) {
        if (coeff < 0) {
            sign = '-';
            abs_coeff = -coeff;
        } else {
            abs_coeff = coeff;
        }
        is_first = 0; // 首项已处理
    } else {
        if (coeff < 0) {
            sign = '-';
            abs_coeff = -coeff;
        } else {
            sign = '+';
            abs_coeff = coeff;
        }
    }

    // 输出符号
    if (sign != '\0') putchar(sign);

    // 输出系数和指数
    if (exp == 0) {
        printf("%dx^0", abs_coeff); // 常数项
    } else {
        if (abs_coeff == 1) { // 系数为1或-1时省略1
            printf("x^%d", exp);
        } else {
            printf("%dx^%d", abs_coeff, exp);
        }
    }
}

// 处理所有项系数为0的情况
if (is_first) printf("0");
printf("\n");
关键点:
  • 符号处理
    • 首项:若系数为负,添加负号;正系数不显示符号。
    • 非首项:正系数前加+,负系数前加-
  • 系数显示优化
    • 系数为1-1时,省略1(如+x^2而非+1x^2)。
    • 指数为0时,直接显示为常数项(如5x^0)。
  • 全零处理 :若所有项系数为0,输出0

3. 示例分析

输入样例1:

复制代码

2
5
0 2   1 4   5 7   7 10   8 19
4
0 3   2 6   4 19   5 -9
合并过程:
  • 指数0:2 + 3 = 5 → 5x^0
  • 指数1:4 → 4x^1
  • 指数2:6 → 6x^2
  • 指数4:19 → 19x^4
  • 指数5:7 + (-9) = -2 → -2x^5
  • 其他指数直接保留(如7、8)
输出结果:

复制代码

5x^0+4x^1+6x^2+19x^4-2x^5+10x^7+19x^8

4. 潜在问题与改进

  1. 指数范围限制
    • 若指数超过MAX_EXP,程序会越界。可动态分配内存或使用哈希表优化。
  2. 系数为0的冗余存储
    • 数组存储稀疏多项式时浪费空间,链表结构更高效(但代码复杂度增加)。
  3. 输出顺序
    • 当前按指数升序输出,若需降序需反向遍历数组。
1. 符号输出逻辑

c复制代码

if (sign != '\0') putchar(sign);
  • 作用 :根据系数的正负输出符号(+- 或不输出)。
  • 关键逻辑
    • 首项 :若系数为负,输出 -;若为正,不输出符号 (通过 sign 保持为 \0 实现)。
    • 非首项 :若系数为负,输出 -;若为正,输出 +
  • 示例
    • 首项为 5x^0,无需符号。
    • 后续项 4x^1 前添加 +,形成 +4x^1
    • 若首项为 -2x^5,则直接输出 -2x^5

2. 系数与指数的输出逻辑

c复制代码

if (exp == 0) {
    printf("%dx^0", abs_coeff); // 常数项
} else {
    if (abs_coeff == 1) { // 系数绝对值为1时省略1
        printf("x^%d", exp);
    } else {
        printf("%dx^%d", abs_coeff, exp);
    }
}
  • 作用:根据指数和系数的不同情况,生成对应的字符串。
  • 关键逻辑
    • 指数为0(常数项)
      • 无论系数是否为1,均保留系数(如 5x^01x^0)。
      • 例如:输入项 0 1 输出为 1x^0
    • 指数非0
      • 若系数绝对值为1(如 1-1),省略系数,只输出 x^指数
      • 例如:1x^2 输出为 x^2-1x^3 输出为 -x^3(符号由 sign 处理)。
  • 示例
    • 输入项 5 75 -9 合并后系数为 -2,输出为 -2x^5
    • 输入项 4 1 输出为 x^4

3. 全零多项式处理逻辑

c复制代码

if (is_first) printf("0");
  • 作用 :若多项式所有项系数均为0,输出 0
  • 关键逻辑
    • is_first 初始为 1,表示尚未输出任何项。
    • 遍历所有指数后,若 is_first 仍为 1,说明所有项系数均为0。
  • 示例
    • 输入两个多项式 0 30 -3,合并后系数为0,输出 0

总结

  • 符号处理 :通过 sign 动态控制符号显示,确保首项无多余 +
  • 系数优化:对系数为1或-1的项简化输出,提升可读性。
  • 全零检测 :利用 is_first 标记判断是否所有项均被抵消。

多项式合并后的输出逻辑末尾,具体位置如下:


if (is_first) printf("0");
printf("\n");

这两行代码位于多项式合并后的输出逻辑末尾,具体位置如下:

代码位置说明

// 遍历所有指数(从0到MAX_EXP)输出非零项
for (int exp = 0; exp <= MAX_EXP; exp++) {
    // ...符号和系数处理逻辑...
}

// 以下代码在遍历完所有指数后执行
if (is_first) printf("0"); // 处理全零多项式
printf("\n");              // 换行

作用详解

1. if (is_first) printf("0");
  • 目的:处理两个多项式相加后所有项系数均为0的特殊情况。
  • 逻辑
    • is_first 初始化为 1,表示"尚未输出任何项"。
    • 在遍历指数时,若遇到非零项,is_first 会被置为 0
    • 如果遍历完所有指数后,is_first 仍为 1,说明所有项系数均为0,此时需要输出 0
  • 示例
    • 输入多项式 0 30 -3,合并后系数为0 → 输出 0
2. printf("\n");
  • 目的:每组多项式处理完成后换行,符合题目要求的输出格式。

  • 示例

    text复制代码

    输入:
    2
    第一组多项式...
    第二组多项式...
    
    输出:
    第一组结果
    第二组结果  // 每组结果占一行
    

代码执行流程图

复制代码

开始处理一组多项式
↓
遍历所有指数,输出非零项 → 若有非零项,is_first = 0
↓
遍历结束
↓
if (is_first == 1) → 输出 "0" // 全零多项式
↓
输出换行符 "\n"

示例分析

假设输入的两个多项式相加后所有项系数均为0:

c复制代码

// 合并后的多项式系数:
result = 0
result[1] = 0
...
result[MAX_EXP] = 0

// 遍历所有指数时:
所有项系数为0 → 跳过所有输出 → is_first 保持为1

// 遍历结束后:
if (is_first) printf("0"); // 输出0
printf("\n");              // 换行

最终输出:0\n(即 0 后换行)。


总结

  • 位置:这两行代码在多项式项遍历结束后执行。
  • 作用
    1. 处理全零多项式(输出 0)。
    2. 确保每组结果独占一行。

优化版本代码

优化点说明

  1. 提取重复逻辑为函数 :将多项式输入逻辑封装为 read_polynomial 函数,消除重复代码。
  2. 简化符号处理 :使用 abs 函数直接计算绝对值,合并符号判断逻辑。
  3. 优化条件分支:减少嵌套条件层级,提升可读性。
  4. 增强边界检查:确保指数不越界(虽然题目假设输入合法,但增加检查更鲁棒)。

优化后代码

c复制代码

// 引入标准输入输出库和数学库
#include <stdio.h>   // 提供printf、scanf等输入输出函数
#include <stdlib.h>  // 提供abs绝对值函数

// 定义多项式最高指数为10000
#define MAX_EXP 10000

// 函数:读取多项式并合并到结果数组
void read_polynomial(int term_count, int result[]) {
    // 循环读取每个多项式项
    for (int i = 0; i < term_count; i++) {
        int exp, coeff;
        // 读取指数和系数(输入格式示例:"3 5" 表示5x^3)
        scanf("%d %d", &exp, &coeff);
        
        // 边界检查:确保指数在合法范围内
        if (exp >= 0 && exp <= MAX_EXP) {  
            // 将系数累加到对应指数位置(多项式相加的核心操作)
            result[exp] += coeff;  // 等效于 result[exp] = result[exp] + coeff
        }
    }
}

int main() {
    // 读取测试用例数量
    int n;
    scanf("%d", &n);
    
    // 处理每个测试用例
    while (n--) {  // 循环n次,每次n减1直到为0
        // 初始化结果数组(所有元素设为0)
        int result[MAX_EXP + 1] = {0};  // 数组下标范围[0,10000]
        
        // 读取第一个多项式
        int A;
        scanf("%d", &A);  // 读取项数
        read_polynomial(A, result);  // 调用函数合并到结果数组
        
        // 读取第二个多项式(处理方式同上)
        int B;
        scanf("%d", &B);
        read_polynomial(B, result);

        // ========== 输出合并后的多项式 ==========
        int is_first = 1;  // 标记是否是首项(用于处理符号)
        for (int exp = 0; exp <= MAX_EXP; exp++) {  // 遍历所有指数
            int coeff = result[exp];  // 获取当前指数对应的系数
            
            // 跳过系数为0的项(不需要输出)
            if (coeff == 0) continue;

            // 计算绝对值系数(用于显示)
            int abs_coeff = abs(coeff);  // 例如:-3 → 3
            
            // 确定符号逻辑:
            // 首项:负号显示"-",正号不显示符号
            // 非首项:负号显示"-",正号显示"+"
            char sign = is_first ? 
                (coeff < 0 ? '-' : '\0') :  // 首项符号处理
                (coeff < 0 ? '-' : '+');    // 非首项符号处理

            // 输出符号(非首项需要输出)
            if (!is_first) {
                putchar(sign);  // 输出'+'或'-'
            }

            // 输出当前项的内容
            if (exp == 0) {  // 常数项特殊处理
                // 格式说明:
                // is_first为真时:负号已包含在sign,正号不需要符号
                // is_first为假时:符号已通过putchar输出
                printf("%s%dx^0", 
                    is_first ? (coeff < 0 ? "-" : "") : "",  // 首项负号处理
                    abs_coeff);
            } else {  // 非常数项
                if (abs_coeff == 1) {  // 系数绝对值为1时省略1
                    // 格式说明:
                    // is_first为真时:无需符号(例如首项是x^2)
                    // is_first为假时:通过sign判断符号
                    printf("%sx^%d", 
                        is_first ? "" : (sign == '+' ? "+" : "-"), 
                        exp);
                } else {
                    // 常规输出(显示系数和指数)
                    printf("%s%dx^%d", 
                        is_first ? "" : (sign == '+' ? "+" : "-"), 
                        abs_coeff, 
                        exp);
                }
            }
            
            // 标记已输出过至少一项
            is_first = 0;  // 后续项都不是首项
        }

        // 处理全零多项式(未输出任何项时)
        if (is_first) {
            printf("0");  // 例如:输入多项式0x^3 + 0x^5
        }
        
        // 每个测试用例后换行
        printf("\n"); 
    }
    
    return 0;  // 程序正常退出
}

关键优化解释

1. 函数封装 (read_polynomial)
  • 作用:统一处理多项式输入逻辑,避免重复代码。
  • 优势:代码更简洁,修改输入逻辑时只需调整一处。
2. 符号处理优化
  • 原逻辑:分别处理首项和非首项的符号。
  • 优化后 :通过 is_first 标志统一处理,减少嵌套条件。
3. 绝对值计算
  • 原代码:手动判断正负计算绝对值。
  • 优化后 :直接使用 abs(coeff),代码更简洁。
4. 边界检查
  • 新增逻辑 :在 read_polynomial 中检查指数是否在 [0, MAX_EXP] 范围内,避免数组越界。

测试用例

输入

复制代码

2
2
0 5 3 -2
3
1 4 3 2 5 1
2
0 -1 1 1
2
0 1 1 -1
输出

复制代码

5x^0+4x^1+0x^3+1x^5  // 合并后:5 +4x^1 +0x^3 +1x^5
0                    // 全零多项式

总结

优化后的代码在以下方面提升:

  • 可维护性:通过函数封装减少重复代码。
  • 可读性:简化符号处理逻辑,减少条件嵌套。
  • 鲁棒性:增加输入边界检查。
  • 性能 :使用标准库函数 abs() 提升效率。
相关推荐
大数据追光猿3 分钟前
Python应用算法之贪心算法理解和实践
大数据·开发语言·人工智能·python·深度学习·算法·贪心算法
Dream it possible!20 分钟前
LeetCode 热题 100_在排序数组中查找元素的第一个和最后一个位置(65_34_中等_C++)(二分查找)(一次二分查找+挨个搜索;两次二分查找)
c++·算法·leetcode
夏末秋也凉21 分钟前
力扣-回溯-46 全排列
数据结构·算法·leetcode
南宫生21 分钟前
力扣每日一题【算法学习day.132】
java·学习·算法·leetcode
柠石榴26 分钟前
【练习】【回溯No.1】力扣 77. 组合
c++·算法·leetcode·回溯
Leuanghing26 分钟前
【Leetcode】11. 盛最多水的容器
python·算法·leetcode
qy发大财27 分钟前
加油站(力扣134)
算法·leetcode·职场和发展
王老师青少年编程27 分钟前
【GESP C++八级考试考点详细解读】
数据结构·c++·算法·gesp·csp·信奥赛
qy发大财28 分钟前
柠檬水找零(力扣860)
算法·leetcode·职场和发展
瓦力的狗腿子30 分钟前
Starlink卫星动力学系统仿真建模番外篇6-地球敏感器
算法·数学建模·simulink