纪检监察网站建设 讲话用dw制作学校网站教程
本题要求输入两个一元多项式,然后输出它们的和(相加后得到的一元多项式)
输入格式:
输入一个整数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) { // 若从未输出过项,说明结果全为0printf("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}; // 初始化结果数组为0int 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时省略1printf("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时省略1printf("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()
提升效率。