题目内容:
一个多项式可以表达为x的各次幂与系数乘积的和,比如:
2x6+3x5+12x3+6x+20
现在,你的程序要读入两个多项式,然后输出这两个多项式的和,也就是把对应的幂上的系数相加然后输出。
程序要处理的幂最大为100。
输入格式:
总共要输入两个多项式,每个多项式的输入格式如下:
每行输入两个数字,第一个表示幂次,第二个表示该幂次的系数,所有的系数都是整数。第一行一定是最高幂,最后一行一定是0次幂。
注意第一行和最后一行之间不一定按照幂次降低顺序排列;如果某个幂次的系数为0,就不出现在输入数据中了;0次幂的系数为0时还是会出现在输入数据中。
输出格式:
从最高幂开始依次降到0幂,如:
2x6+3x5+12x3-6x+20
注意其中的x是小写字母x,而且所有的符号之间都没有空格,如果某个幂的系数为0则不需要有那项。
输入样例:
6 2
5 3
3 12
1 6
0 20
6 2
5 3
2 12
1 6
0 20
输出样例:
4x6+6x5+12x3+12x2+12x+40
时间限制:500ms内存限制:32000kb
最初的很直接的思路:
①数据读入时第一个数字读到0则完成第一个多项式的读入;循环两次完成两组多项式读入,为储存幂次方和系数建立4个数组并记录每个数组的有效数字大小
②将数组按照幂级数从大到小进行选择排序,系数也按照对应位置进行交换,重复两次
③以最大的幂级数进行递减搜索,对应幂次的系数的位相加,可视为进行相同幂次的搜索
④遍历输出:需要考虑正负号、系数为1时不输出1,幂次为1时也只输出“%dx,幂次为0系数正常输出,某个幂的系数为0则不需要有那项,但需要注意只有0的情况
但这个思路过于直接,重复循环和步骤很多,效率低,事实上是可以进行简化的。而且对于输出,目前只能确定满足MOOC中的测试样例,可能还有细节没有注意到。
#include<stdio.h>
int search(int key, int a[], int len); // 搜索函数
int main()
{
const int maxnumber = 101; //多项式最大项数
int power1[101] = {0} , co1[101] = {0}; // 第一个多项式的幂次和系数
int power2[101] = {0} , co2[101] = {0}; // 第二个多项式的幂次和系数
int i,j;
int cnt1 = 0, cnt2 = 0; //记录两个多项式的项数,即power1和power2的有效数组长度
// 输入
do{
scanf("%d %d", &power1[cnt1], &co1[cnt1]);
cnt1 ++; //最终获得power1的有效数组长度
} while( power1[cnt1-1]!=0 );
do{
scanf("%d %d", &power2[cnt2], &co2[cnt2]);
cnt2 ++; //最终获得power2的有效数组长度
} while( power2[cnt2-1]!=0 );
// 选择排序:将数组按照幂次从高到低排序(即数值从大到小),系数保证对应位置共同移动,首尾已分别确定是最大和最小
int maxid;
for( j=1; j<cnt1-2 ; j++){ //j为待排序数组的第一个元素起始下标
maxid = j; //初始时总是设置最左的数组元素为最大值所在位置
for( i=j+1; i<cnt1-1; i++){
if( power1[i]>power1[maxid] ){
maxid = i;
}
}
int t = power1[maxid]; // 把最大值固定在数组最左
power1[maxid] = power1[j];
power1[j] = t;
int c = co1[maxid]; // 系数数组同步交换
co1[maxid] = co1[j];
co1[j] = c;
}
for( j=1; j<cnt2-2 ; j++){ //j为待排序数组的第一个元素起始下标
maxid = j; //初始时总是设置最左的数组元素为最大值所在位置
for( i=j+1; i<cnt2-1; i++){
if( power2[i]>power2[maxid] ){
maxid = i;
}
}
int t = power2[maxid]; // 把最大值固定在数组最左
power2[maxid] = power2[j];
power2[j] = t;
int c = co2[maxid]; // 系数数组同步交换
co2[maxid] = co2[j];
co2[j] = c;
}
// 搜索:对应幂次的系数的位相加,可视为进行相同幂次的搜索,以max{power1[0],power2[0]}作为最高幂次,依次搜索
int maxpower = power1[0]>power2[0] ? power1[0] : power2[0]; // maxpower为max{power1[0],power2[0]} 为最大幂次
int co[maxpower+1]; // 最终结果多项式的储存数组,安装对应幂次从高到低记录其系数 ,如co[0] 是maxpower幂级次对应的系数
for( i=0 ; i<=maxpower ; i++ ) { // 数组初始化
co[i] = 0;
}
for( i=maxpower ; i>=0 ; i--){ //循环遍历确定某一幂次是否存在
int loc1 = search(i, power1, cnt1);
int loc2 = search(i, power2, cnt2);
if( loc1!=-1 && loc2!=-1){ // 枚举法,或许也考虑使得search返回值在查找不到时对应到某个数组的位置,这个位置内部是0值,就可以避免这种枚举相加
co[maxpower-i] = co1[loc1] + co2[loc2];
} else if( loc1!=-1 && loc2==-1 ){
co[maxpower-i] = co1[loc1];
} else if( loc1==-1 && loc2!=-1 ){
co[maxpower-i] = co2[loc2];
} else{
co[maxpower-i] = 0;
}
}
// 遍历输出
int loc = 0;
for( i=0 ; i<maxpower+1 ; i++){
if( co[i]!= 0 && co[i]!=1 ){
loc = i; // 系数不为0的最大幂次位置
printf("%dx%d", co[loc], maxpower-loc);
break;
}
if( co[i]==1 ){
loc = i; // 系数不为0的最大幂次位置
printf("x%d", maxpower-loc);
break;
}
}
if( i==maxpower+1 && co[maxpower]==0 ) printf("0");
for( i=loc+1 ; i<maxpower+1 ; i++){ //由于有加号和x的幂次方,故幂次为1和0时不进入这次循环,单独输出
if( co[i]>0 ){
printf("+") ;
}
if( co[i]!=0 && co[i]!=1 ){
if( i==maxpower-1 ) printf("%dx", co[i]) ;
else if( i==maxpower ) printf("%d", co[i]) ;
else printf("%dx%d", co[i], maxpower-i) ;
}
if( co[i]==1 ){
if( i==maxpower-1 ) printf("x") ;
else if( i==maxpower ) printf("1") ;
else printf("x%d", maxpower-i) ;
}
}
return 0;
}
/* 搜索
@param key 要查找的数值
@param a 待查找的数组
@param len 数组a的长度
return 返回key在数组a中的位置,查找不到则返回-1
*/
int search(int key, int a[], int len)
{
int ret = -1; // 查找不到返回-1,否则返回在数组中的位置(下标)
int i;
for( i=0 ; i<len ; i++){
if( a[i]==key ){
ret = i;
break;
}
}
return ret;
}
改进(其实没改很多):
①由于每个多项式以0次幂作为结尾,故在输入时进行0出现的计数,出现次数为2时停止输入,两个多项式不需要分别进行输入;
②由于最终实现的是多项式加和,输入时不需要分清两个多项式的起始,同意进行幂次从大到小排序即可,注意系数需要一起移动,后续仍然使用搜索进行相同幂次的系数相加
③遍历输出的思路分为0,仅有0次幂,有非0次幂的情况,在非0次幂时由于第一项前无正号进行了单独讨论,对于系数为1的情况进行了单独讨论,也区分了幂次为1的情况的输出
感觉这个题整体方法写的很麻烦,感觉有很大改动空间,但是基本功能能实现
#include<stdio.h>
int main()
{
int power1[202] = {0} , co1[202] = {0}; // 分别储存幂次和系数,幂最大100,故输入最多(100+1)*2
int i,j;
int cnt1 = 0; //记录power1的有效数组长度
int cnt0 = 0; //记录输入0的个数作为循环条件
// 输入
do{
scanf("%d %d", &power1[cnt1], &co1[cnt1]);
cnt1 ++;
if( power1[cnt1-1]==0 ) cnt0 ++ ;
} while( cnt0!=2 );
// 选择排序:将数组按照幂次从高到低排序(即数值从大到小),系数保证对应位置共同移动
int maxid;
for( j=0; j<cnt1-1 ; j++){ //j为待排序数组的第一个元素起始下标
maxid = j; //初始时总是设置最左的数组元素为最大值所在位置
for( i=j+1; i<cnt1; i++){
if( power1[i]>power1[maxid] ){
maxid = i;
}
}
int t = power1[maxid]; // 把最大值固定在数组最左
power1[maxid] = power1[j];
power1[j] = t;
int c = co1[maxid]; // 系数数组同步交换
co1[maxid] = co1[j];
co1[j] = c;
}
// 搜索:对应幂次的系数的位相加,可视为进行相同幂次的搜索,以power1[0]作为最高幂次,由于以经过排序,故可进行双重循环遍历,power中的值不相等时既可以停止累加
int maxpower = power1[0]; // maxpower最大幂次
int co[maxpower] ; // 最终结果多项式的储存数组,安装对应幂次从高到低记录其系数 ,如co[0] 是maxpower幂级次对应的系数
for( i=0 ; i<=maxpower ; i++ ) { // 数组初始化
co[i] = 0;
}
for( i=maxpower ; i>=0 ; i-- ){ //循环遍历,相同幂次加和
for( j=0; j<cnt1 ; j++){
if( power1[j]==i ){
co[maxpower-i] += co1[j];
}
}
}
// 遍历输出
int loc = maxpower+1; // 系数不为0的最大幂次位置
for( i=0 ; i<maxpower+1 ; i++){
if( co[i]!= 0 ){
loc = i;
break;
}
}
if( loc==maxpower+1 ) printf("0"); // 系数全部为0
else if( loc==maxpower ) printf("%d", co[maxpower]); // 只有0次幂(即数字)
else if( loc<maxpower){ //存在非0次幂输出
if( co[loc]==1 ){
if( loc==maxpower-1 ) printf("x") ;
else printf("x%d", maxpower-i) ;
} else if( co[loc]!=0 ) {
if( loc==maxpower-1 ) printf("%dx",co[loc]) ;
else printf("%dx%d", co[loc], maxpower-loc) ;
}
for( i=loc+1 ; i<maxpower+1 ; i++){ //由于有加号和x的幂次方,故幂次为1和0时不进入这次循环,单独输出
if( co[i]>0 ){
printf("+") ;
}
if( co[i]==1 ){
if( i==maxpower-1 ) printf("x") ;
else if( i==maxpower ) printf("1") ;
else printf("x%d", maxpower-i) ;
} else if( co[i]!=0 ){
if( i==maxpower-1 ) printf("%dx", co[i]) ;
else if( i==maxpower ) printf("%d", co[i]) ;
else printf("%dx%d", co[i], maxpower-i) ;
}
}
}
return 0;
}
测试用例尝试了:
①
6 2
5 3
3 12
1 6
0 20
6 2
5 3
2 12
1 6
0 20
②
0 0
4 1
2 1
1 1
0 1
③
4 -1
2 -1
1 -1
0 -1
0 2
④
4 -1
2 -1
1 -1
0 -1
0 0
⑤
4 12
3 -6
2 2
1 1
0 2
4 -12
3 6
0 0
⑥
0 0
0 0