hdu3892 Common Roots 最大取模公因式

本文讨论了多项式模运算下是否存在共根的问题,通过实例解释了如何判断多个多项式是否共有根,并提供了算法实现。对于每组输入多项式,文章详细介绍了计算过程,最终输出是否共有根的结论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

We have many polynomials modulo p (p is a prime number). An interesting issue would be to determine whether they have some roots in common. Notice roots we mention here are integers in modulo p system (0 <= root < p). Moreover, if the given polynomial is of order r, we will guarantee that it has r roots.
For example, we have
x^2 + 13x + 36 (mod 37)
x^3 + 14x^2 + 49x + 36 (mod 37)
If x = 33 or x = 28, both of them would give the value of 0. So 33 and 28 are the roots in common.
 

Input
There are many test cases (less than1000).
In each case, the integer in the first line is n (the number of polynomials in this case). Then n lines followed. Each of them starts with an integer r (order of polynomials, r <= 50), and r + 1 integers (a(r), a(r-1) ,..., a(0)), which means the polynomial goes like:
a(r) * x^r + a(r-1) * x^(r-1) + … +a(1) * x + a(0) (mod 999983).
To make it easier, p is set to be 999983, as you see.
 

Output
For each case, just output “YES” if they have common roots, otherwise “NO” in a single line.
 

Sample Input
2 2 1 13 36 3 1 14 49 36
 

Sample Output
YES

  是否存在解,满足每个式子取模后都为0。

  求出这些式子的公因式,如果最大系数大于0的话肯定有解。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define eps 1e-9
#define MAXN 1010
#define MAXM 110
#define MOD 999983
typedef long long LL;
using namespace std;
LL N,M;
vector<LL> ans,g[MAXN];
void gcd(LL a,LL b,LL& d,LL& x,LL& y){
    if(!b){
        d=a;
        x=1;
        y=0;
    }
    else{
        gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
LL inv(LL a,LL n){
    LL d,x,y;
    gcd(a,n,d,x,y);
    return d==1?(x+n)%n:-1;
}
vector<LL> poly_gcd(vector<LL> a,vector<LL> b){
    if(!b.size()) return a;
    int L=a.size()-b.size()+1,bs=b.size(),as=a.size();
    for(LL i=0;i<L;i++){
        LL t=(a[i]*inv(b[0]%MOD,MOD))%MOD;
        for(LL j=0;j<bs;j++) a[i+j]=(a[i+j]-b[j]*t%MOD+MOD)%MOD;
    }
    vector<LL> c;
    LL flag=0;
    for(LL i=0;i<as;i++){
        if(a[i]){
            flag=1;
            for(LL j=i;j<as;j++) c.push_back(a[j]);
        }
        if(flag) break;
    }
    return poly_gcd(b,c);
}
int main(){
    freopen("in.txt","r",stdin);
    LL cas=0;
    while(scanf("%I64d",&N)!=EOF){
        for(LL i=0;i<N;i++) g[i].clear();
        for(LL i=0;i<N;i++){
            scanf("%I64d",&M);
            LL t;
            for(LL j=0;j<M+1;j++){
                scanf("%I64d",&t);
                g[i].push_back(t);
            }
        }
        if(N==1) ans=g[0];
        else{
            ans=poly_gcd(g[0],g[1]);
            for(LL i=2;i<N;i++) ans=poly_gcd(ans,g[i]);
        }
        if(ans.size()>1) puts("YES");
        else puts("NO");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值