题目
引理
秦九韶算法:一个n次多项式的计算可以通过逆乘法分配律转为只有n次加法+n次乘法的计算。百科走起
题解
数论
有人用高精度吗?好东西呀!
在有上面的引理后,我们可以O(N)判定i是否为方程的解,这样枚举个i差不多就过了。
如何判断和是否为0呢?直接、暴力的想法就是高精计算,但这样会T的。我们可以考虑用模,这样就避免了爆long long。但是这样容易出现玄学WA,最好用多个模数,降低意外出现的可能性。
有一个剪枝,假设模数为P,方程用f(x)=0来表示。
如果f(x)=0,那么f(x+k*P)=0。反过来同样正确。
所以如果一个数x,没有f(x%P)=0,这个数不可能是方程的解。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll P=10007,Q=1000000007;
const int MAXN=110;
int n,m;
ll a[MAXN],b[MAXN];
bool v[P];
int tot=0,list[MAXN];
bool check(int x,int mod,ll *t)
{
ll s=t[n];
for(int i=n-1;i>=0;i--) s=(s*x+t[i])%mod;
return s==0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)
{
char ch=getchar();bool f=false;
while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
while(ch>='0' && ch<='9') a[i]=(a[i]*10+(ch^48))%P,b[i]=(b[i]*10+(ch^48))%Q,ch=getchar();
if(f) a[i]=-a[i],b[i]=-b[i];
}
for(int i=0;i<P;i++)
if(check(i,P,a)) v[i]=true;
for(int i=1;i<=m;i++)
if(v[i%P] && check(i,Q,b)) list[++tot]=i;
printf("%d\n",tot);
for(int i=1;i<=tot;i++) printf("%d\n",list[i]);
return 0;
}