UVa 10951 Polynomial GCD
题目大意:
给定两个
Zn
上的多项式
f(x)
和
g(x)
,求出他们的
gcd
,即
Zn
上的一个多项式
r(x)
,使得其可以同时整除
f(x)
和
g(x)
,且次数尽量大.你找到的多项式的最高项系数应当为
1
.
(注意:
题目分析:
求解最大公因数的方法是辗转相除法,也可以推广求最大公因式,问题在于如何定义模运算.
因为模运算的结果一定小于模数,如
a=x4+x3+x2+x+1,b=x2+x+1
所以
a%b
的结果一定是小于b的,那么结果的最高次项一定小于b的最高此项.
那么将
a
中的
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define inv(x) pow_mod(x,MOD-2)
int MOD;
int pow_mod(int x,int y)
{
int ret=1;
while(y>0) {
if(y&1) ret=ret*x%MOD;
x=x*x%MOD;y>>=1;
}
return ret;
}
struct Polynomial {
vector<int>poly;
Polynomial operator % (const Polynomial& rhs) const {//a%b就是指将a中比b次数高的项抵消掉
Polynomial tmp=*this,ret;
int t=tmp.poly.size()-rhs.poly.size();
int v=inv(rhs.poly[0]);
for(int i=0;i<=t;i++) {
int d=tmp.poly[i]*v%MOD;
for(int j=0;j<rhs.poly.size();j++)
(tmp.poly[i+j]-=d*rhs.poly[j]%MOD-MOD)%=MOD;
}
int pos=-1;
for(int i=0;i<tmp.poly.size();i++)
if(tmp.poly[i]!=0) {pos=i;break;}
if(pos>=0) for(int i=pos;i<tmp.poly.size();i++)
ret.poly.push_back(tmp.poly[i]);
return ret;
}
void input() {
poly.clear();
int n;
scanf("%d",&n);
for(int t,i=0;i<=n;i++) {
scanf("%d",&t);
poly.push_back(t);
}
}
void output() {
printf("%d",poly.size()-1);
int v=inv(poly[0]);
for(int i=0;i<poly.size();i++) printf(" %d",poly[i]*v%MOD);
}
}f,g,ans;
Polynomial gcd(Polynomial a,Polynomial b)
{
return b.poly.size()?gcd(b,a%b):a;
}
int main()
{
int kase=0;
while(scanf("%d",&MOD)==1&&MOD) {
f.input();g.input();
ans=gcd(f,g);
printf("Case %d: ",++kase);
ans.output();
printf("\n");
}
return 0;
}