MOOC-W7-多项式加法

题目内容:

一个多项式可以表达为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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值