POJ 1060/ ZOJ 1026 : Modular Multiplication of Polynomials - f(x)g(x) mod h(x)

多项式乘法、模除

题意:

给出f(x),g(x),h(x)的 (最高次幂+1)的值,以及它们的各项系数,求f(x)*g(x)/h(x)的余数。

这里多项式的系数只有1或0,

因为题目要求:这里多项式的加减法是将系数相加/减后再模2,这样其实也就可以用异或运算来代替加减法。

思路:

主要在于把除法转化成减法,一次一次减。

用sum[]数组存结果,最高次幂为ls,各项系数存在f[ls-1 … 0]

1 - 计算乘积,

多项式的系数只有1或0,故最高次幂ls = lf + lg -1,f[i]*g[j](i、j为指数的值),相当于位的与运算f[i]&g[j],结果加到x^(i+j)的系数上,即sum[i+j]+=f[i]&g[j];

2 - 计算模除。

sum(x)对h(x)取模,即除以h(x)直到余数小于h(x),此余数即取模的结果,关键在于判别sum(x)、h(x)的大小。

若ls>lh,则sum大;让sum(x)除以h(x):

对h,按次幂由低到高,进行相除运算,h[i]异或到sum[i+ls-lh],即sum[i+d] ^= h[i],然后重新调整sum的最高次幂(while(ls&&!sum[ls-1])-ls)

ls<lh,则h大,得到结果;

若ls=lh,从最高次幂开始逐项比较系数。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1005;

int cmp(int a[], int la, int b[], int lb){//比较多项式a b的大小
	if(la > lb)
		return 1;
	if(la < lb)
		return -1;
	for(int i = la - 1; i >= 0; i--){//a b最高次幂相同时,按次幂由高到低顺序逐项比较
		if(a[i] && !b[i])
			return 1;
		else if(!a[i] && b[i])
			return -1;
	}
	return 0;
}

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		int f[N], g[N], h[N];
		int lf, lg, lh;

		scanf("%d", &lf);//多项式最高次幂
		for(int i = lf - 1; i >= 0; i--)//多项式每一项的系数
			scanf("%d", &f[i]);
		scanf("%d", &lg);
		for(int i = lg - 1; i >= 0; i--)
			scanf("%d", &g[i]);
		scanf("%d", &lh);
		for(int i = lh - 1; i >= 0; i--)
			scanf("%d", &h[i]);

		int sum[N + N], ls = lf + lg - 1;//乘积数组sum、长度初始化
		for(int i = 0; i < ls; i++)
			sum[i] = 0;
		for(int i = 0; i < lf; i++)
			for(int j = 0; j < lg; j++)
				sum[i + j] ^= (f[i] & g[j]);

		//取模
		while(cmp(sum, ls, h, lh) >= 0){//当前余数sum不小于h,则继续除以h
			int d = ls - lh;
			for(int i = 0; i < lh; i++)
				sum[i + d] ^= h[i];
			while(ls && !sum[ls - 1])
				ls--;
		}

		/*if(ls == 0)//舍去这部分无碍
			ls = 1;*/
		printf("%d ", ls);
		for(int i = ls - 1; i > 0; i--)
			printf("%d ", sum[i]);
		printf("%d\n", sum[0]);
	}
	return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值