题目:
This time, you are supposed to find A+B where A and B are two polynomials.
Input Specification:
Each input file contains one test case. Each case occupies 2 lines, and each line contains the information of a polynomial:
K N1 aN1 N2 aN2 … NK aNK
where K is the number of nonzero terms in the polynomial, Ni and aNi (i=1,2,⋯,K) are the exponents and coefficients, respectively. It is given that 1≤K≤10,0≤NK<⋯<N2<N1≤1000.
Output Specification:
For each test case you should output the sum of A and B in one line, with the same format as the input. Notice that there must be NO extra space at the end of each line. Please be accurate to 1 decimal place.
Sample Input:
2 1 2.4 0 3.2
2 2 1.5 1 0.5
Sample Output:
3 2 1.5 1 2.9 0 3.2
分析:
实际上就是求一元N次多项式的和,本题给出了次数的限制(0≤NK<⋯<N2<N1≤1000.),因此用一个元素个数大于1000的数组可以很简单的实现。
因为最近刚刚开始学链表,所以尝试用链表来做这道题,就是代码有点长,应该还可以短很多。
代码:
//
// Created by dgm on 19-2-25.
//
#include <iostream>
#include <cmath>
#include<iomanip>
using namespace std;
typedef struct ElemType{
float E;
int N;
}ElemType;
typedef struct ListNode{
ListNode()
:next(NULL)
{}
ElemType data;
ListNode* next;
unsigned int Length=0;
}*Node;
void Init_List(Node&L,int n)
{
float E;
int N;
L=new ListNode();
auto p=L;
for(int i=0;i<n;i++)
{
cin>>N>>E;
Node temp=new ListNode();
temp->data.E=E;
temp->data.N=N;
p->next=temp; //p始终指向L尾部
p=p->next; //尾插法
L->Length++;
}
}
void Print_List(Node L)
{
cout<<L->Length;
//if(!L->Length)return;
auto p=L->next;
while(p){
cout<<" "<<p->data.N<<" "<< setiosflags(ios::fixed) << setprecision(1) <<p->data.E;
p=p->next;
}
}
void Add_List(Node&La,Node Lb)
{
auto pa=La->next; //pa指向A中当前元素
auto pb=Lb->next; //pb指向B中当前元素
Node preva=La; //pa的前驱
La->Length+=Lb->Length; //假定和的项数等于
while(pa&&pb) //链表A和链表B项数之和
{ //之后再根据A,B各项的合并情况调整
if(pa->data.N<pb->data.N) //如果B中当前元素的次数高于A中当前元素
{ //则将该元素添加到pa之前
auto temp=pb->next; //记录pb在B中的后继
pb->next=pa;
preva->next=pb;
preva=pb; //preva始终指向pa的前一个元素
pb=temp; //在B中后移pb
}
else if(pa->data.N==pb->data.N) //如果元素次数相等
{
pa->data.E+=pb->data.E; //则系数相加存入A中
if(fabs( pa->data.E)<1e-6) //如果系数之和为0
{
La->Length-=2; //将这一对系数互为相反数的项
auto temp=pa; //同时从A和B中删去,
preva->next=pa->next; //所以减2(联系前边La->Length+=Lb->Length;)。
pa=pa->next; //准备删去pa所指
free(temp);
temp=pb; //准备删去pb所指
pb=pb->next;
free(temp);
continue; //下一轮比较
}
auto temp=pb; //如果系数和不为零
pb=pb->next; //pa,pb都后移
free(temp);
preva=pa;
pa=pa->next;
La->Length--; //相当于合并同类项,长度减1
}
else
{
preva=pa; //如果pa次数高于pb
pa=pa->next; //pa后移,再与pb比较
}
}
if(pb) //如果pb非空,
{ // 说明B中还有剩余项(次数一定比A最小项小)
preva->next=pb; //那么将剩余项连接到A上
}
free(Lb); //B用不着了
}
int main()
{
unsigned int n;
cin>>n;
Node A;
Init_List(A,n);
cin>>n;
Node B;
Init_List(B,n);
Add_List(A,B);
Print_List(A);
return 0;
}
易错:
输出最后没有空格;
系数全部保留一位小数;
系数为0的项不显示;
即使相加之后的元素个数为0,也要输出其个数(0);
注意两多项式中两个元素互为相反数的情况;