多项式域欧几里得

求多项式的最大公约数

模板题:https://cn.vjudge.net/problem/UVA-10951#author=0

给定两个Zn上的多项式f和g,求出它们的gcd,并且次数尽量大,最高项系数为1(加法和乘法均在mod m意义下进行)

#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
int n;
vector<int> f, g;

// 快速幂求逆元
int inv(int a, int n) {
    int res = 1;
    int b = n-2;
    while(b)
    {
        if(b & 1) res = res * a % n;
        a = a * a % n;
        b >>= 1;
    }
    return res;
}

//多项式的最大公约数
vector<int> gcd(vector<int> a,vector<int> b)
{
    if(b.size() == 0) return a;
    int t = a.size() - b.size();
    vector<int> c;
    for(int i=0; i<=t; i++)
    {
        int tmp = a[i] * inv(b[0],n) % n;
        for(int j=0; j<b.size(); j++)
            a[i+j] = (a[i+j] - tmp * b[j] % n + n) % n;
    }
    int p = -1;
    for(int i=0; i<a.size(); i++)
    {
        if(a[i] != 0)
        {
            p=i;
            break;
        }
    }
    if(p >= 0)
        for(int i=p; i<a.size(); i++)
            c.push_back(a[i]);
    return gcd(b,c);
}

int main() {
    int cas = 0;
    while (~scanf("%d", &n) && n) {
        f.clear(); g.clear();
        int a, k;
        scanf("%d", &a);
        for (int i = 0; i <= a; i++)
        {
            scanf("%d", &k);
            f.push_back(k);
        }
        scanf("%d", &a);
        for (int i = 0; i <= a; i++)
        {
            scanf("%d", &k);
            g.push_back(k);
        }
        vector<int> ans = gcd(f, g);
        int tmp = inv(ans[0], n), ansz = ans.size();
        printf("Case %d: %d", ++cas, ansz - 1);
        for (int i = 0; i < ansz; i++)
        {
            printf(" %d", ans[i] * tmp % n);
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/WTSRUVF/p/9326571.html