多项式A除以B

这个问题我是在PAT大区赛题里遇见的。题目如下:

多项式A除以B(25 分)

这仍然是一道关于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

题目的意思很明确,就是要求 anxn+an-1xn-1+an-2xn-2+。。。+a1x1+a0x0 除以amxm+am-1xm-1+am-2xm-2+。。。+a1x1+a0x0 的商和余数。这可以类比多项式除法进行。这题的样例数据可表示为:x4-3x2-x-1 除以 3x2-2x+1 求其的商和余数。

手工计算步骤就是下图所示:依次乘一个(1/3)x2,(2/9)x,(-26/27),很明显就是想办法消掉最高次项,知道所剩的余项最高次小于除数的最高次。

分数化简后就为答案。(上方为商,下方为余数)。

算法核心部分上面已经讲了,接下来讲一下数据结构的设置。

因为每一项都是指数、系数这两个变量,所以我们可以用STL中的map来存储这一个<指数,系数>键值对。

因此我在此设了三个map数组

map<int,double> a;    //多项式A(最后的余数)
map<int,double> b;    //除数
map<int,double> c;    //商

多项式A的初始化

1 cin>>lena;    //A多项式的项数
2 for(int i=0;i<lena;i++){
3     int e;
4     double c;
5     cin>e;
6     cin>>c;
7     maxe_a = max(maxe_a,e);//找到A的最高次指数
8     a[e] = a[e] + c;    //相同系数即刻合并
9 }

多项式B同理,但要注意多求一个最小项次数。

接下来,最重要的来了,那就是除法运算的过程。首先我们先知道要进行几次除法的运算。由上面的示例步骤我们可以知道,运算次数为:( A的最高次幂 - B的最高次幂 )+ 1 次,也可理解为( i = max (eA); i >= max(eB); i --)这样的过程。

商的其中一项就是(当前A的最高次幂系数 / B的最高次幂系数)这是系数,指数为 (当前A的最高次幂 - B的最高次幂),为什么加一个当前呢?因为A每次最高项都会被(B的最高次项 * 相应商的一项)所消掉,直至A最终变为要求的余数项为止。

余数项,就是A每一项每次被 (B的每项 * 相应项的商)做差后系数没被削成0的项。

 1 for(int i = maxe_a;i>=maxe_b;i--){
 2     if(b[maxe_b]!=0){
 3         div = 1.0*a[i]/b[maxe_b];
 4         //printf("div=%.1lf\n",div);
 5         sub = i - maxe_b;
 6         c[sub] = div;
 7         maxe_c = max(maxe_c,sub);    //求商的最高次幂
 8                  //每次从剩余项的最高次开始,直到B的最低次,每项做差
 9         for(int j=i;j>=mine_b;j--){
10             if(j-sub >= 0){
11                 a[j] = a[j] - b[j-sub]*c[sub];
12             }
13         }
14     }
15 }

之后c[ ] 就是商,a[ ] 就是余数项。

最后依据题意,为c[ ]数组 a[ ]数组做下四舍五入。接下来讲一下怎么做四舍五入。

因为题目要求保留一位有效数字,所以就先把这个数*10化为(int)+/-0.5,再除以10即可。今后碰见四舍五入问题一次类推!

for(int i=maxe_c;i>=0;i--){
    //四舍五入处理
    c[i] = (double)((int)(c[i]*10 + (c[i]<0?-0.5:0.5)))/10;
    if(c[i]){
        cnt++;
    }
}   

最后奉上此题解的原码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<map>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7
 8 map<int,double> a;
 9 map<int,double> b;
10 map<int,double> c;
11 int lena,lenb;
12
13 int main(){
14     int maxe_a = 0,mine_b=32767,maxe_b=0,maxe_c=0;
15     double div;
16     int sub;
17     cin>>lena;
18     for(int i=0;i<lena;i++){
19         int e;
20         double c;
21         cin>>e;
22         cin>>c;
23         maxe_a = max(maxe_a,e);    //找到A的最高次指数
24         a[e] = a[e] + c;    //相同系数即刻合并
25     }
26     cin>>lenb;
27     for(int i=0;i<lenb;i++){
28         int e;
29         double c;
30         cin>>e;
31         cin>>c;
32         mine_b = min(mine_b,e);    //找到B的最低次指数
33         maxe_b = max(maxe_b,e);    //找到B的最高次指数
34         b[e] = b[e] + c;    //相同系数即刻合并
35     }
36     for(int i = maxe_a;i>=maxe_b;i--){
37         if(b[maxe_b]!=0){
38             div = 1.0*a[i]/b[maxe_b];
39             //printf("div=%.1lf\n",div);
40             sub = i - maxe_b;
41             c[sub] = div;
42             maxe_c = max(maxe_c,sub);    //求商的最高次幂
43             for(int j=i;j>=mine_b;j--){        //每次从剩余项的最高次开始,直到B的最低次,每项做差
44                 if(j-sub >= 0){
45                     a[j] = a[j] - b[j-sub]*c[sub];
46                 }
47             }
48         }
49     }
50     int cnt=0;
51     for(int i=maxe_c;i>=0;i--){
52         c[i] = (double)((int)(c[i]*10 + (c[i]<0?-0.5:0.5)))/10;//四舍五入处理
53         if(c[i]){
54             cnt++;
55         }
56     }
57     if(cnt ==0){
58         printf("0 0 0.0\n");
59     }else{
60         printf("%d",cnt);
61         for(int i=maxe_c;i>=0;i--){
62             if(c[i]){
63                 printf(" %d %.1lf",i,c[i]);
64             }
65         }
66         printf("\n");
67     }
68     cnt =0;
69     for(int i = maxe_a;i>=0;i--){
70         a[i] = (double)((int)(a[i]*10 + (a[i]<0?-0.5:0.5)))/10;//四舍五入处理
71         if(a[i]){
72             cnt++;
73         }
74     }
75     if(cnt ==0){
76         printf("0 0 0.0");
77     }else{
78         printf("%d",cnt);
79         for(int i=maxe_a;i>=0;i--){
80             if(a[i]){
81                 printf(" %d %.1lf",i,a[i]);
82             }
83         }
84     }
85     return 0;
86 }



最后总结一下,像这题可以作为多项式相除的模板题目。以后还可用于多项式的因式分解,求方程根等问题。

参考:cccc L2-018. 多项式A除以B



原文地址:https://www.cnblogs.com/javier2018/p/8511774.html

时间: 2024-10-10 10:09:06

多项式A除以B的相关文章

团体程序设计天梯赛 L2-018. 多项式A除以B(模拟)

题意:给你A,B两个多项式,问你A/B的值:注意多项式给你的是每个式子的指数与系数:保留到一位小数,如果出现系数为0(保留后也是)的情况,请不要输出它,如果没有非系数为0的情况就输出特殊 题解:多项式类似于"a*x^4+b*x^3+c*x^2+d*x^1+e*x^0"的形式,两个多项式除法就是模拟除法做 现在被除数最大指数的系数.被 除数最大指数的系数除以.结果就是商的系数,两个指数的差就是商的指数 然后枚举除数每一位乘以这个值来被 被除数减去,最后找被除数后一个位置继续循环,直到被除

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个非零项的系数.各项按照指数递减的顺序给出,保证所有指数是各不相同的非负整数,所有系数是非零整数,所有整数在整型范围内. 输出格式: 分两行先后输出商和余,输出

PAT L2-018. 多项式A除以B

暴力,模拟. 比赛搞了一个小时搞到了$1$分.赛场上不够冷静......之前没接触过多项式除法,但赛场上想到了除法的规则,莫名其妙写的时候不知道哪里崩了.对于这样的题目,应该先测一测数据的指数是不是很大,指数不大开数组存就可以了. #include<bits/stdc++.h> using namespace std; double eps=1e-1; double a[5010],b[5010],c[5010]; int n; int main() { memset(a,0,sizeof a

Matlab 学习之旅(一)

一.脚本文件和M函数 1.1  脚本文件      脚本文件是命令行的集合,由一系列 MATLAB 命令.内置函数及M 文件等组成的文件.脚本文件在MATLAB 编译器中建立,并被保存为.m文件,按顺序执行,执行过程中生成的变量存放在当前工作空间中.     注意:脚本不能返回输出变量,所有创建的变量将保留在工作空间中,但脚本能提供图形输出,就像使用图形输出函数plot()一样. 例子:    利用M文件编辑器,键入命令并保存为magicrank.m        array = zeros(1

【信号与系统】多项式化简方法

多项式长除法 简介 ??? ? ? ? 多项式长除法?是代数中的一种算法,用一个同次或低次的多项式去除另一个多项式.是常见算数技巧长除法的一个推广版本.它可以很容易地手算,因为它将一个相对复杂的除法问题分解成更小的一些问题. 示例 计算 ? 把被除式.除式按某个字母作降幂排列,并把所缺的项用零补齐,写成以下这种形式: ? 然后商和余数可以这样计算: 将分子的第一项除以分母的最高次项(即次数最高的项,此处为x).结果写在横线之上(x3?÷?x?=?x2). 将分母乘以刚得到结果(最终商的第一项),

秦九韶算法求解多项式

秦九韶算法是中国南宋时期的数学家秦九韶提出的一种多项式简化算法.在西方被称作霍纳算法.它是一种将一元n次多项式的求值问题转化为n个一次式的算法. 一般地,一元n次多项式的求值需要经过[n(n+1)]/2次乘法和n次加法,而秦九韶算法只需要n次乘法和n次加法.其大大简化了计算过程,即使在现代,利用计算机解决多项式的求值问题时,秦九韶算法依然是最优的算法. 题目:写程序计算给定多项式在给定点x处的值 f(x) = a0 + a1x + … + an-1xn-1 + anxn 分析:对比使用常规算法和

[学习笔记] 多项式与快速傅里叶变换(FFT)基础

引入 可能有不少OIer都知道FFT这个神奇的算法, 通过一系列玄学的变化就可以在 $O(nlog(n))$ 的总时间复杂度内计算出两个向量的卷积(或者多项式乘法/高精度乘法), 而代码量却非常小. 博主一年半前曾经因COGS的一道叫做"神秘的常数 $\pi$"的题目而去学习过FFT, 但是基本就是照着板子打打完并不知道自己在写些什么鬼畜的东西OwO 不过...博主这几天突然照着算法导论自己看了一遍发现自己似乎突然意识到了什么OwO然后就打了一道板子题还1A了OwO再加上午考试差点AK

高次多项式因式分解

一. 1.商式 在多项式除法P(x)/Q(x)运算中,如果P(x)可以表示成Q(x)*S(x)+R(x)的形式(其中S(x).R(x)为整式),那么S(x)叫该除法式中的商式. 例1:求(x^3-2)/(x+1)的商式 解:(x^3-2)/(x+1) =(x^3+1-3)/(x+1) =(x^3+1)/(x+1)-3/(x+1) =(x^2-x+1)-3/(x+1) 所以 商式为x^2-x+1 例2:(2x^3-4x^2-1)/(x^2-2x-1/2)的商式是_____. 解:原式=2x+(x-

多项式求值

一.一维多项式求值: P(x)=3x^6+7x^5+3x^4+3x^3+8x^2+5x+23 一个通用的计算多项式的值的算法可以采用递推的方式.首先可以将上面多项式变形为如下的等价方式: P(x)=(...((an-1x+an-2)x+an-3)x+...+a1)x+a0 通过以上表达式可以看出,只要从里往外逐层按照如下的方式递推,便可以计算得到一个一维多项式的值: Rk=Rk+1*x+ak 具体示例代码如下: 1 /* 2 * @author 3 * 一维多项式求值,从最高一项开始迭代计算 4