题目
思路
我们称多项式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;
}