天梯团队赛 L2-018 多项式A除以B

题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805060372905984

L2-018 多项式A除以B

这仍然是一道关于A/B的题,只不过A和B都换成了多项式。你需要计算两个多项式相除的商Q和余R,其中R的阶数必须小于B的阶数。

输入格式:

输入分两行,每行给出一个非零多项式,先给出A,再给出B。每行的格式如下:

N e[1] c[1] … e[N] c[N]

其中N是该多项式非零项的个数,e[i]是第i个非零项的指数,c[i]是第i个非零项的系数。各项按照指数递减的顺序给出,保证所有指数是各不相同的非负整数,所有系数是非零整数,所有整数在整型范围内。

输出格式:

分两行先后输出商和余,输出格式与输入格式相同,输出的系数保留小数点后1位。同行数字间以1个空格分隔,行首尾不得有多余空格。注意:零多项式是一个特殊多项式,对应输出为0 0 0.0。但非零多项式不能输出零系数(包括舍入后为0.0)的项。在样例中,余多项式其实有常数项-1/27,但因其舍入后为0.0,故不输出。

输入样例:
4 4 1 2 -3 1 -1 0 -1
3 2 3 1 -2 0 1
输出样例:
3 2 0.3 1 0.2 0 -1.0
1 1 -3.1
题目分析

本题主要有3个需要考虑的点:

  1. 多项式的除法运算
  2. 数据结构的选择
  3. 保留1位小数后,有效数值的处理
一、首先解决多项式除法问题

多项式的除法简单的来说,就是每次运算凑出被除数的最高次方的项,然后就能一次次的将被除数的最高次方给降下来,直到最高次方小于除数的次方。

拿题目的样例来说:
被除数: x 4 − 3 x 2 − x − 1 x^{4}-3 x^{2}-x-1 x43x2x1
除数: 3 x 2 − 2 x + 1 3x^{2}-2x+1 3x22x+1

在这里插入图片描述
被除数最大次方的项是 x 4 x^{4} x4 那就凑出来,将除数乘上一个 1 3 x 2 \frac{1}{3} x^{2} 31x2
在这里插入图片描述
同理,再次凑出最大次方的项,只需要乘上一个 2 9 x \frac{2}{9}x 92x
在这里插入图片描述
一样的,最后我们乘上一个 − 26 27 -\frac{26}{27} 2726 就是最后的答案了
在这里插入图片描述
题目要求进行保留1位小数所以结果就是:
商: 0.3 x 2 + 0.2 x − 1.0 0.3x^{2}+0.2x-1.0 0.3x2+0.2x1.0
余数: − 3.1 x − 0.0 -3.1x-0.0 3.1x0.0

二、其次解决数据结构选择的问题

本题数据结构的选择有很多种,我采用的是两个数组 e[] 和 c[] 分别保存指数系数
但是其实你也可以使用 Map 容器来保存,key就是指数,value是系数;或者如果你不知道如何使用Map,那你也可以使用结构体+数组的方式,总的来说,数据结构有着很多的选择,不同的数据结构处理起来也有不同的方式。

三、最后解决保留小数1位小数的问题

题目要求保留1位小数,并且是经过舍入后的结果,如果你使用的是C语言的 printf("%.1lf")那么你就不需要考虑舍入的问题,这种方式会自动四舍五入。
如果你不是使用这种方式舍入,那么你可以对输出的结果加上一个0.05,然后保留1位小数,这样也能起到四舍五入的效果。

AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

int e[3][50000];  		//  指数 
double c[3][50000];  	//  系数
int a[50000];			// 辅助数组
double b[50000];		// 辅助数组


void run(int id, int n) { // 处理最后的结果,并输出
	int allN = 0;
	for(int i=0;i<n;i++) { // 过滤无效值,并且重新确定项数
		if(fabs(c[id][i]) > 0.04) {
			a[allN] = e[id][i];
			b[allN++] = c[id][i];
		}
	} 
	if(allN == 0) {
		cout<<"0 0 0.0"<<endl;
	} else {
		cout<<allN<<" ";
		for(int i=0;i<allN-1;i++){
			printf("%d %.1lf ", a[i], b[i]);
		}
		printf("%d %.1lf\n", a[allN-1], b[allN-1]);
	}
}

int main(int argc, char *argv[]) {
	int n1,n2;
	cin>>n1;
	for(int i=0;i<n1;i++) {	// 输入被除数 
		cin>>e[0][i]>>c[0][i];
	}
	cin>>n2;
	for(int i=0;i<n2;i++) { // 输入除数 
		cin>>e[1][i]>>c[1][i];
	}
	int id = 0;	// 标记被除数最大次方
	int sum = 0;// 记录运算了几次
	while(e[0][id] >= e[1][0]) { // 循环条件:被除数最大次方>=除数最大次方
		double rt[2][50000]; // 缓存减数
		double result[2][50000]; // 对减结果
		int i,j,s=0; // s是对减结果新的项数
		// 凑出最大项要乘的数
		e[2][sum] = e[0][id] - e[1][0];
		c[2][sum] = c[0][id] / c[1][0];
		for(i=0;i<n2;i++) {  // 得出减数
			rt[0][i] = e[2][sum]+e[1][i];
			rt[1][i] = c[2][sum]*c[1][i];
		}
		i = 0;
		j = 0;
		while(i < n1 && j < n2) {	// 归并的思想进行对减,保证次幂从大到小 
			while(i < n1 && c[0][i] == 0) { // 排除系数为0的情况
				i++;
			}
			if(i >= n1) break;
			if(rt[0][j] == e[0][i]) {
				result[0][s] = e[0][i];
				result[1][s++] = c[0][i] - rt[1][j];
				i++;
				j++;
			} else if(rt[0][j] > e[0][i]) {
				result[0][s] = rt[0][j];
				result[1][s++] = -rt[1][j];
				j++;
			} else {
				result[0][s] = e[0][i];
				result[1][s++] = c[0][i];
				i++;
			}
		}
		while(j < n2) {
			result[0][s] = rt[0][j];
			result[1][s++] = -rt[1][j++];
		}
		while(i < n1) {
			result[0][s] = e[0][i];
			result[1][s++] = c[0][i++];
		}
		int res = -1; // 标记有效的最大次方项的下标(因为有系数为0的项)
		for(i=0;i<s;i++) {
			e[0][i] = result[0][i];
			c[0][i] = result[1][i];
			if(res < e[0][i] && c[0][i] != 0) {
				res = e[0][i];
				id = i;
			}
		}
		n1 = s;
		sum++;
		if(res == -1) {
			break;
		}
	}
	run(2, sum);
	run(0, n1);
	return 0;
}

温馨提示:注意输出格式问题,末尾不要有多余的空格。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hiram Fan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值