POJ 3471 Integral Roots(素数、因数)

题目链接:http://poj.org/problem?id=3471

题意:给出一个多项式f(x),求f(x)=0所有的整数根。

 

思路:由于求的是f(x)的整数根,设它的整数根分别为x1,x2……,则f(x)可以写成这种形式:

f(x)=a*(x-x1)*(x-x2)*(x-x3)*……

f(x)最后的常数为0,则有根0,f(x)可以除掉x,因此总能化成上式。设f(x)最后的常数项为p,我们发现:

p=x1*x2*x3*……,所以只要这样求解即可:

(1)求出p的所有因数组成集合Q;

(2)枚举Q的某个元素xi,若可以使得f(xi)=0,则xi为一个解,f(x)=f(x)/(x-xi);

(3)在Q中继续(2),直到找不到一个xi,结束。

 

那么接下来就是对于一个给定的xi,怎么计算f(xi)是不是等于0?霍纳法则,我以前只知道但是从来没用过:

f(x)=(((x+a)*x+b)*x+c)……就是这个意思,然后找个素数,每次对该素数取模即可。。。

 

 #include <iostream>
 #include <cstdio>
 #include <cstring>
 #include <algorithm>
 #define int64 __int64
 using namespace std;
 
 int64 MOD[]={13251349,13251361,13251367,
              13251373,13251377,13251383};
              
              
 int64 prime[60000],isprime[60000],cnt;
 
 
 void init()
 {
     int64 i,j;
     cnt=0;
     for(i=2;i<60000;i++)
     {
         if(!isprime[i]) prime[++cnt]=i;
         for(j=1;j<=cnt&&prime[j]*i<60000;j++)
         {
             isprime[prime[j]*i]=1;
             if(i%prime[j]==0) break;
         }
     }
 }
 
 struct node
 {
     int64 prime,num;
 };
 
 node a[100];
 int64 n,aNum,factor[10000],factorNum;
 int64 coef[105];
 
 
 int64 ABS(int64 x)
 {
     if(x<0) return -x;
     return x;
 }
 
 void DFS(int64 x,int dep)
 {
     int64 i;
     if(dep==aNum+1)
     {
         factor[factorNum++]=x;
     }
     else
     {
         for(i=0;i<=a[dep].num;i++)
         {
             DFS(x,dep+1);
             x=x*a[dep].prime;
         }
     }
 }
 
 void cal(int64 p)
 {
     aNum=0;
     int64 i;
     for(i=1;i<=cnt;i++) if(p%prime[i]==0)
     {
         aNum++;
         a[aNum].prime=prime[i];
         a[aNum].num=0;
         while(p%prime[i]==0)
         {
             a[aNum].num++;
             p/=prime[i];
         }
     }
     if(p>1)
     {
         aNum++;
         a[aNum].prime=p;
         a[aNum].num=1;
     }
     factorNum=0;
     DFS(1,1);
 }
 
 int OK(int64 a)
 {
     int64 r,b,i,j;
     for(i=0;i<6;i++)
     {
         r=0;
         b=a%MOD[i];
         for(j=n;j>=0;j--) r=(r*b+coef[j])%MOD[i];
         if(r) return 0;
     }
     return 1;
 }
 
 int64 ans[10005],ansNum;
 
 int main()
 {
     init();
     while(scanf("%d",&n)!=-1)
     {
         int64 i,j,k,t,r,u;
         for(i=n-1;i>=0;i--) scanf("%I64d",&coef[i]);
         coef[n]=1;
         ansNum=0;
         k=0;
         factorNum=0;
         while(n)
         {
             if(coef[0]==0)
             {
                 ans[ansNum++]=0;
                 for(i=0;i<n;i++) coef[i]=coef[i+1];
                 n--;
             }
             else
             {
                 if(!factorNum) cal(ABS(coef[0]));
                 t=0;
                 for(i=k;i<factorNum;i++) if(coef[0]%factor[i]==0)
                 {
                     if(OK(factor[i]))
                     {
                         t=factor[i];
                         k=i;
                         break;
                     }
                     if(OK(-factor[i]))
                     {
                         t=-factor[i];
                         k=i;
                         break;
                     }
                 }
                 if(!t) break;
                 ans[ansNum++]=t;
                 r=0;
                 for(i=n;i>=0;i--)
                 {
                     u=r*t+coef[i];
                     coef[i]=r;
                     r=u;
                 }
                 n--;
             }
         }
         sort(ans,ans+ansNum);
         printf("%I64d\n",ansNum);
         for(i=0;i<ansNum;i++) printf("%I64d\n",ans[i]);
     }
     return 0;
 }

 

  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值