【NOI.AC #803】多项式

题目

在这里插入图片描述

在这里插入图片描述

思路

我们称多项式P 整除Q,当且仅当存在某个多项式A,使得Q = A · P。
那么我们可以定义两个多项式P,Q 的最大公因数,记作gcd(P,Q)。这里的大小
是以度数大小作为比较标准,容易证明这样的gcd 是唯一的。
则AP + BQ 的值一定是gcd(P,Q) 的倍数,考虑能不能达到这一点。
如果不是在多项式域中而是在整数域,那么我们相当于要解不定方程ax + by =gcd(a, b),这可以使用扩展欧几里得算法求解。
扩展欧几里得算法的原理是,对于a = kb + t,我们如果有了bx + ty = gcd(a, b)的一组解(x′, y′),那么我们就可以构造出原方程的一组解(y′ − kx′, x′)。
那么对于本题,我们可以同样地进行操作:设P = KQ+T,则我们可以求出方程AQ + BT = gcd(Q, T) 的一组解(A′,B′),然后求出原问题的一组解(B′ − KA′,A′)。
问题在于如何求出K 以及T。
事实上,我们并不需要真的进行取模操作——我们只需要每次去掉多项式P 的最高位即可,则此时K 是一个xk 的形式,那么KQ 可以很容易地通过位运算求出。
因为在mod 2 意义下加法和减法都是异或,因此我们也可以很容易地通过位运算求出T。
于是使用std::bitset 维护两个多项式即可。

代码

#include <bits/stdc++.h>
using namespace std;
bitset<100005> a,b,p,q;
int n,m,k,yjy[200005];
int main() {
	scanf("%d%d",&n,&m);
	n++;
	m++;
	for (int i=0;i<n;i++) {
		int x;
		scanf("%d",&x);
		a.set(i,x);
	}
	for (int i = 0; i < m; i++) {
		int x;
		scanf("%d",&x);
		b.set(i,x);
	}
	while (m) {
		if (n < m) {
			yjy[k++] = -1;
			swap(a,b);
			swap(n,m);
			continue;
		}
		yjy[k++] = n - m;
		a ^= (b << (n - m));
		while (n && !a[n - 1]) n--;
	}
	p.set(0);
	for (int i = k - 1; i >= 0; i--) {
		if (yjy[i] == -1) swap(p,q);
		else q ^= (p << yjy[i]);
	}
	int n1 = 100005,m1 = 100005;
	while (n1 > 1 && !p[n1 - 1]) n1--;
	while (m1 > 1 && !q[m1 - 1]) m1--;
	printf("%d %d\n",n1 - 1,m1 - 1);
	for (int i = 0; i < n1; i++) printf("%d%c",(int)p[i]," \n"[i == n1 - 1]);
	for (int i = 0; i < m1; i++) printf("%d%c",(int)q[i]," \n"[i == m1 - 1]);
	return 0;
}
发布了703 篇原创文章 · 获赞 392 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/Eric1561759334/article/details/104078127