多项式的乘积与和

本题目来源于https://pintia.cn/

题目描述

设计函数分别求两个一元多项式的乘积与和。

输入格式

输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式

输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0。

输入样例

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1

输出样例

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

本文采用了4中方式解决该问题,这四种方式其实遵循的算法是一样的,只是每种方式采用了不同的数据存储结构。
对于这个问题,比较核心的算法是处理两式相乘的思路,主要有两种:
逐次插入法:

  • L1的第一项分别于L2各项相乘,得到一个结果式L
  • L1其余各项分别于L2各项相乘,保存相乘结果c和e
  • 根据结果指数e寻找应该插入到L的位置
    • 若该位置的指数小于e,则将节点插入到该位置之前
    • 若该位置的指数等于e,判断该位置的系数与c之和是否为0
      • 为0则删除该节点
      • 不为0则将该节点的系数进行更新

乘法转换为加法:(算法一的方法二采用该思想)

  • 创建一个结果式子L,再创建一个临时式子tmp
  • tmp用于存放每次L1一项与L2各项相乘的结果
  • L1每完成一项的相乘,就将L和tmp做一次加法运算

算法一:采用链表进行存储

方法一:自定链表操作

这种方式是遵循MOOC上浙大数据结构给出的方式,虽然在程序中使用了C++的语法,但是设计思想还是C语言的思想,采用传统的定义链表节点的方式存储数据。这种方式适合练习链表的使用,相关操作包含了链表的插入,查找,删除操作。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
//定义数据结构
typedef struct Node* Poly;
struct Node{int coef;int expon;Poly next;
};
//读取数据
Poly Read()
{int n;cin >> n;Poly Head = (Poly)malloc(sizeof(struct Node));Poly p = Head;while(n--){int tmp1,tmp2;cin >> tmp1 >> tmp2;if(tmp1 != 0)   //对于零多项式,不将其输入到链表中{Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = tmp1;tmp->expon = tmp2;p->next = tmp;p = p->next;}}p->next = NULL;        //数据输入完成后需要将链表的尾指针置空return Head;
}
//多项式相乘
Poly Multiply(Poly L1,Poly L2)
{if(L1->next == NULL)    //如果存在0多项式,则两个多项式相乘返回的是0,即返回自身return L1;if(L2->next == NULL)    return L2;Poly Head = (Poly)malloc(sizeof(struct Node));Poly p = Head;Poly p1 = L1->next;Poly p2 = L2->next;while(p2){//先生成一个结果链表,L1的第一项分别于L2的各项相乘Poly tmp = (Poly)malloc(sizeof(struct Node));int c = p1->coef * p2->coef;int e = p1->expon + p2->expon;tmp->coef = c;tmp->expon = e;p->next = tmp;p = p->next;p2 = p2->next;}p->next = NULL;        //生成结果链表后要将尾指针置空,因为后面的操作不只是简单的插入了p1 = p1->next;while(p1){p2 = L2->next;p = Head;while(p2){int c = p1->coef * p2->coef;int e = p1->expon + p2->expon;//寻找符合条件的插入位置,该条件为指数不能大于前面的元素while(p->next && p->next->expon > e)p = p->next;//找到插入位置后,如果该位置的指数恰好为e,则要进行系数合并;若小于e,则进行节点插入if(p->next && p->next->expon == e){//如果系数之和不为0,则更新链表中的系数;为0则删除该节点if(c + p->next->coef != 0)p->next->coef += c;else{Poly tmp = p->next;p->next = tmp->next;free(tmp);}}else{Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = c;tmp->expon = e;tmp->next = p->next;p->next = tmp;}p2 = p2->next;}p1 = p1->next;}return Head;
}
//多项式相加
Poly Sum(Poly L1,Poly L2)
{if(L1->next == NULL)    //如果存在零多项式,则两式相加,返回另一个多项式return L2;if(L2->next == NULL)return L1;Poly Head = (Poly)malloc(sizeof(struct Node));Poly p = Head;Poly p1 = L1->next;Poly p2 = L2->next;while(p1 && p2){if(p1->expon > p2->expon){Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = p1->coef;tmp->expon = p1->expon;p->next = tmp;p = p->next;p1 = p1->next;}else if(p1->expon < p2->expon){Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = p2->coef;tmp->expon = p2->expon;p->next = tmp;p = p->next;p2 = p2->next;}else{int sum = p1->coef + p2->coef;if(sum != 0){Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = sum;tmp->expon = p1->expon;p->next = tmp;p = p->next;}p1 = p1->next;p2 = p2->next;}}while(p1){Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = p1->coef;tmp->expon = p1->expon;p->next = tmp;p = p->next;p1 = p1->next;}while(p2){Poly tmp = (Poly)malloc(sizeof(struct Node));tmp->coef = p2->coef;tmp->expon = p2->expon;p->next = tmp;p = p->next;p2 = p2->next;}p->next = NULL;return Head;
}
//输出多项式结果
void Print(Poly L)
{if(L->next == NULL)cout << 0 << " " << 0 << endl;else{Poly p = L->next;while(p){if(p->next == NULL)cout << p->coef << " " << p->expon;elsecout << p->coef << " " << p->expon << " ";p = p->next;}cout << endl;}}
int main()
{Poly L1 = Read();Poly L2 = Read();Poly L3 = Multiply(L1,L2);Poly L4 = Sum(L1,L2);Print(L3);Print(L4);
}

方法二:使用List容器

这里使用的是C++的list容器,并且采用了将乘法转变为加法的思想。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;typedef struct Node Poly;
struct Node{int coef;int expon;
};
list<Poly> Read()
{int n;cin >> n;list<Poly> L;while(n--){int tmp1,tmp2;cin >> tmp1 >> tmp2;if(tmp1 != 0){Poly tmp;tmp.coef = tmp1;tmp.expon = tmp2;L.push_back(tmp);}}return L;
}
list<Poly> Sum(list<Poly> L1,list<Poly> L2)
{if(L1.begin() == L1.end())return L2;if(L2.begin() == L2.end())return L1;list<Poly> L;auto it1 = L1.begin();auto it2 = L2.begin();while(it1 != L1.end() && it2 != L2.end()){if(it1->expon > it2->expon){L.push_back(*it1);it1++;}else if(it1->expon < it2->expon){L.push_back(*it2);it2++;}else{int tmp = it1->coef + it2->coef;if(tmp != 0){Poly t;t.coef = tmp;t.expon = it1->expon;L.push_back(t);}it1++;it2++;}}while(it1 != L1.end()){L.push_back(*it1);it1++;}while(it2 != L2.end()){L.push_back(*it2);it2++;}return L;
}
list<Poly> Multiply(list<Poly> L1,list<Poly> L2)
{if(L1.begin() == L1.end())return L1;if(L2.begin() == L2.end())return L2;list<Poly> L;for(auto it1 = L1.begin();it1 != L1.end();it1++){list<Poly> tmp;for(auto it2 = L2.begin();it2 != L2.end();it2++){int c = (it1->coef) * (it2->coef);int e = (it1->expon) + (it2->expon);Poly t;t.coef = c;t.expon = e;if(c != 0)tmp.push_back(t);}L = Sum(L,tmp);}return L;
}
void Print(list<Poly> L)
{if(L.begin() == L.end())cout << 0 << " " << 0;else{for(auto it = L.begin();it != L.end();it++){if(it == L.begin())cout << it->coef << " " << it->expon;elsecout << " " << it->coef << " " << it->expon;}}cout << endl;
}
int main()
{list<Poly> L1 = Read();list<Poly> L2 = Read();list<Poly> L3 = Multiply(L1,L2);list<Poly> L4 = Sum(L1,L2);Print(L3);Print(L4);return 0;
}

算法二:采用动态数组存储

这里采用的方式是动态数组,使用了C++的vector容器。这里主要是对容器进行初始化操作,每次进行操作都是作为对象进行的。采用这种方式的好处是可以直接使用vector的一些模板函数,简化编程。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
typedef struct node LNode;
//相当于构建了LNode类
struct node{int coef;int expon;
};
vector<LNode> Read()
{int n;cin >> n;vector<LNode> L;while(n--){int tmp1,tmp2;cin >> tmp1 >> tmp2;if(tmp1 != 0){LNode tmp;tmp.coef = tmp1;tmp.expon = tmp2;L.push_back(tmp);}}return L;
}
vector<LNode> Multiply(vector<LNode> L1,vector<LNode> L2)
{if(L1.begin() == L1.end())return L1;if(L2.begin() == L2.end())return L2;vector<LNode> L;auto it1 = L1.begin();for(auto it2 = L2.begin();it2 != L2.end();it2++){int c = (*it1).coef * (*it2).coef;int e = (*it1).expon + (*it2).expon;LNode tmp;tmp.coef = c;tmp.expon = e;L.push_back(tmp);}if(it1 != L1.end())it1++;else return L;for(;it1 != L1.end();it1++){for(auto it2 = L2.begin();it2 != L2.end();it2++){auto it = L.begin();int c = (*it1).coef * (*it2).coef;int e = (*it1).expon + (*it2).expon;while((*it).expon > e && it < L.end())it++;if(it == L.end()){LNode tmp;tmp.coef = c;tmp.expon = e;L.push_back(tmp);}else{if((*it).expon == e){if((*it).coef + c != 0)it->coef += c;else{L.erase(it);}}else{LNode tmp;tmp.coef = c;tmp.expon = e;L.insert(it,tmp);}}}}return L;
}
vector<LNode> Sum(vector<LNode> L1,vector<LNode> L2)
{if(L1.begin() == L1.end())return L2;if(L2.begin() == L2.end())return L1;vector<LNode> L;auto it1 = L1.begin();auto it2 = L2.begin();while(it1 != L1.end() && it2 != L2.end()){if((*it1).expon > (*it2).expon){L.push_back(*it1);it1++;}else if((*it1).expon < (*it2).expon){L.push_back(*it2);it2++;}else{if((*it1).coef + (*it2).coef != 0){LNode tmp;tmp.coef = (*it1).coef + (*it2).coef;tmp.expon = (*it1).expon;L.push_back(tmp);}it1++;it2++;}}while(it1 != L1.end()){L.push_back(*it1);it1++;}while(it2 != L2.end()){L.push_back(*it2);it2++;}return L;
}
void Print(vector<LNode> L)
{if(L.begin() == L.end()){cout << 0 << " " << 0;}else{for(auto it = L.begin();it != L.end();it++){if(it == L.begin())cout << (*it).coef << " " << (*it).expon;elsecout << " " << (*it).coef << " " << (*it).expon;}}cout << endl;
}
int main()
{vector<LNode> L1 = Read();vector<LNode> L2 = Read();vector<LNode> L3 = Multiply(L1,L2);vector<LNode> L4 = Sum(L1,L2);Print(L3);Print(L4);return 0;
}

算法三:采用map容器存储

这个采用的是C++的map容器.其实map容器和unordered_map容器在使用上是一致的,所以也可以采用unordered_map来实现。他们的区别在于map底层由红黑树支持的,而后者使用哈希表支持的。此题采用map时存储顺序有些变化,为<expon,coef>.这样存的好处在于指数是唯一的,正好符合map的键唯一的特性。

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
map<int,int> Read()
{int n;cin >> n;map<int,int> M;while(n--){int tmp1,tmp2;cin >> tmp1 >> tmp2;if(tmp1 != 0)M.insert(pair<int,int>(tmp2,tmp1));}return M;
}
map<int,int> Multiply(map<int,int> M1,map<int,int> M2)
{if(M1.begin() == M1.end())return M1;if(M2.begin() == M2.end())return M2;map<int,int> M;auto it1 = M1.begin();auto it2 = M2.begin();while(it2 != M2.end()){auto c = (it1->second) * (it2->second);auto e = (it1->first) + (it2->first);if(c != 0)M.insert(pair<int,int>(e,c));it2++;}it1++;while(it1 != M1.end()){it2 = M2.begin();while(it2 != M2.end()){auto c = (it1->second) * (it2->second);auto e = (it1->first) + (it2->first);auto it = M.find(e);    //寻找map中是否已存储了eif(it != M.end()){  //已存储了就执行判断语句//如果相加后系数为0,则删掉该键值对if((it->second) + c == 0)M.erase(it);else  //如果不为0,则更新该系数(it->second) += c;}else   //未找到键为e的键值对,就直接插入M.insert(pair<int,int>(e,c));it2++;}it1++;}return M;
}
map<int,int> Sum(map<int,int> M1,map<int,int> M2)
{if(M1.begin() == M1.end())return M2;if(M2.begin() == M2.end())return M1;auto it1 = M1.begin();auto it2 = M2.begin();map<int,int> M;//直接将L1复制到结果式中while(it1 != M1.end()){int c = it1->second;int e = it1->first;M.insert(pair<int,int>(e,c));it1++;}//将L2存入结果式中时,需要判断式中是否已有对应的指数,若存在,则要进行同类项合并,检查结果是否为0//不存在则插入   while(it2 != M2.end()){int e = it2->first;int c = it2->second;auto tmp = M.find(e);if(tmp == M.end())M.insert(pair<int,int>(e,c));else{int t = tmp->second;if(t + c == 0)M.erase(tmp);elsetmp->second += c;}it2++;}return M;
}
void Print(map<int,int> M)
{if(M.begin() == M.end())cout << 0 << " " << 0;else{for(auto it = M.rbegin();it != M.rend();it++){//map中的迭代器不支持it+1之类的操作,所以输出方式进行一下调整//map中的数据是按照键值升序排列的,而此题要求降序输出,所以使用反向迭代器实现if(it  == M.rbegin())cout << it->second << " " << it->first;elsecout << " " << it->second << " " << it->first;}}cout << endl;
}
int main()
{map<int,int> M1 = Read();map<int,int> M2 = Read();map<int,int> M3 = Multiply(M1,M2);map<int,int> M4 = Sum(M1,M2);Print(M3);Print(M4);return 0;
}

算法探究2--多项式的乘积与和相关推荐

  1. Python一句话实现秦九韶算法快速计算多项式的值

    关于秦九韶算法快速计算多项式值的原理描述请参考之前推送的文章Python使用秦九韶算法求解多项式的值.本文重点演示Python函数reduce()和lambda表达式的用法.代码没加注释,如果不好理解 ...

  2. 多项式算法7:多项式除法

    多项式算法7:多项式除法 多项式除法 前置知识: FFT NTT 多项式求逆 多项式除法 算法简述: 给定多项式FFF , GGG求出多项式RRR,QQQ使得F=G×Q+RF=G \times Q + ...

  3. 搜索中常见数据结构与算法探究(二)

    本文介绍了几个常见的匹配算法,通过算法过程和算法分析介绍了各个算法的优缺点和使用场景,并为后续的搜索文章做个铺垫:读者可以通过比较几种算法的差异,进一步了解匹配算法演进过程以及解决问题的场景:KMP算 ...

  4. simca算法 matlab,SIMCA分类法中主成分分析算法探究.doc

    SIMCA分类法中主成分分析算法探究 SIMCA分类法中主成分分析算法探究 摘要:模式识别是研究用计算机模拟人的识别能力,对不同类型形式的数据进行描述.分类.识别等有关的理论和方法.SIMCA方法是基 ...

  5. 多项式算法5:多项式求逆

    多项式算法5:多项式求逆 多项式求逆 前置知识: FFT NTT 多项式求逆 这里的多项式求逆,其实是求多项式的逆元. 对于多项式A(x)A(x)A(x),如果存在A(x)B(x)≡1(modxn)A ...

  6. 朴素贝叶斯算法系列:多项式贝叶斯、高斯贝叶斯、伯努利贝叶斯

    导入库 from sklearn.naive_bayes import MultinomialNB, GaussianNB, BernoulliNB 多项式贝叶斯 def MultinomialNB_ ...

  7. [算法] 两个质数的乘积是707829217,求解该质数

    记录一次有趣的算法题. 土生土长的北京妞儿,在胡同里长大,房不多,就一个四合院和近郊的别墅.不算美如天仙但还算标致,在清华读的经管,现在在做基金经理(不想被人肉,就不暴露单位啦) ,个人擅长基本面分析 ...

  8. 【基础】秦九昭算法实现的多项式快速计算

    秦九昭算法 图片来自搜狗百科 #include <iostream> using namespace std; void main() {int num, x;//num为多项式阶数,x为 ...

  9. 基于sklearn随机森林算法探究肥胖的成因

    目录 项目背景 数据介绍 数据来源 属性介绍 算法介绍 随机森林算法 决策树 随机森林定义 随机森林构建过程 随机森林算法评价 随机森林算法的发展现状及趋势 实验步骤 1.导入模块与数据 2.查看数据 ...

最新文章

  1. Bootstrap下拉菜单组件
  2. 为什么只有很少的人听说过西工大这个名字?
  3. SoapUI 请求 https 报 javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
  4. 网页打印问题,打印设置,打印预览,打印分页,纵打,横打及页面的边距
  5. (网络编程)URL下载网络资源
  6. 【svn老玩家翻车了,git玩的不够6】git恢复本地误删的文件
  7. 顺序表和链表的优缺点理解
  8. 获取http请求标头_HTTP请求和标头参数的CDI拦截器–简单示例
  9. 光纤收发器长距离的传输过程出现死机的解决方案
  10. 编写一个程序实现方法的覆盖java_编写Java程序代码必须先声明一个____,然后在其中编写实现需求的业务代码。...
  11. java web 局部刷新页面_如何实现页面局部刷新(Java)
  12. 有一定的php基础,求推荐PHP框架,本人有一定PHP基础。
  13. c语言递归调用程序,3个C语言实例带你掌握递归方法论
  14. Webpower中国区发布《2015年中国金融保险行业邮件营销市场报告》
  15. 获得当天的 零点 和 当天的最后 一秒的时刻
  16. 可验证随机函数(Verifiable Random Function, VRF)
  17. 搭讪技巧,希望所有单身的程序员兄弟都有女朋友哦!!
  18. arm服务器芯片尺寸,华为公开ARM服务器芯片“Hi1620”:7nm+64核心
  19. html表单的基本结构
  20. 菜鸟弟弟从零开始的爬取Bilibili弹幕的Python爬虫教程-哔哩哔哩 - ( ゜- ゜)つロ 干杯~

热门文章

  1. SpringCloud升级之路2020.0.x版-13.UnderTow 核心配置
  2. 微信小程序获取地理位置失败原因及解决方案
  3. 28. 实战:基于selenium实现12306自动购票
  4. DataTables初始化配置选项学习
  5. 浅谈uf8mb4字符集
  6. ant-design中对单个或多个table列表数据进行动态列合并
  7. [源码和文档分享]Qt实现的宠物小精灵对战游戏阶段二-用户的联网注册和登录...
  8. 2023 网站MySSL安全认证图标及代码
  9. win7系统安装vs2013出现“cannot find one or more components .Please reinstall the application”解决办法
  10. python王者战斗_用 Python 自动玩王者荣耀,简直不要太秀!