本题要求输入两个一元多项式,然后输出它们的和(相加后得到的一元多项式)
输入格式:
输入一个整数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或-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; // 程序正常退出
}
代码解释
- 输入处理 :首先读取测试数据的组数
n
。对于每组数据,分别读取两个多项式的项数及其对应的指数和系数,并将这些系数累加到结果数组中。 - 合并多项式:通过遍历两个多项式,将对应指数的系数相加,存储在结果数组中。
- 输出结果:遍历结果数组,按指数升序输出所有非零项。处理每个项的符号和格式,确保正确显示系数为1或-1的情况,以及首项的符号处理。
- 特殊情况处理:如果所有项的系数均为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. 潜在问题与改进
- 指数范围限制 :
- 若指数超过
MAX_EXP
,程序会越界。可动态分配内存或使用哈希表优化。
- 若指数超过
- 系数为0的冗余存储 :
- 数组存储稀疏多项式时浪费空间,链表结构更高效(但代码复杂度增加)。
- 输出顺序 :
- 当前按指数升序输出,若需降序需反向遍历数组。
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^0
、1x^0
)。 - 例如:输入项
0 1
输出为1x^0
。
- 无论系数是否为1,均保留系数(如
- 指数非0 :
- 若系数绝对值为1(如
1
或-1
),省略系数,只输出x^指数
。 - 例如:
1x^2
输出为x^2
,-1x^3
输出为-x^3
(符号由sign
处理)。
- 若系数绝对值为1(如
- 指数为0(常数项) :
- 示例 :
- 输入项
5 7
和5 -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 3
和0 -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 3
和0 -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
后换行)。
总结
- 位置:这两行代码在多项式项遍历结束后执行。
- 作用 :
- 处理全零多项式(输出
0
)。 - 确保每组结果独占一行。
- 处理全零多项式(输出
优化版本代码
优化点说明
- 提取重复逻辑为函数 :将多项式输入逻辑封装为
read_polynomial
函数,消除重复代码。 - 简化符号处理 :使用
abs
函数直接计算绝对值,合并符号判断逻辑。 - 优化条件分支:减少嵌套条件层级,提升可读性。
- 增强边界检查:确保指数不越界(虽然题目假设输入合法,但增加检查更鲁棒)。
优化后代码
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()
提升效率。