BZOJ-3751[NOIP2014]解方程(秦九韶算法+hash)
题目描述
已知多项式方程:
\[a_0+a_1x+a_2x^2+\cdots+a_nx^n=0
\]
求这个方程在 \([1,m]\) 内的整数解(\(0<n\leq 100,|a_i|\leq 10^{10000},a_n\neq 0,m<10^6\))。
分析
根据秦九韶算法:
\[\begin{aligned}&A(x)\\=&a_nx^n+a_{n-1}x^{n-1}+\cdots+a_1x+a_0\\
=&(a_nx^{n-1}+a_{n-1}x^{n-2}+\cdots+a_2x+a_1)x+a_0\\
=&((a_nx^{n-2}+a_{n-3}x^{n-2}+\cdots+a_3x+a_2)x+a_1)x+a_0\\
=&(\cdots((a_nx+a_{n-1})x+a_{n-2})x+\cdots+a_1)x+a_0
\end{aligned}
\]
由内向外逐层计算一次多项式的值。
\(a_i\) 非常大,将其对一个大质数取模(比如 \(998244353\)),由于 \(A(x)=0\),则 \(A(x)\equiv 0\pmod {p}\),所以取模后用秦久韶算法再检验是正确的(为了防止哈希冲突可以多选几个模数)。
代码
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
inline long long read()
{
long long x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=(x*10%mod+ch-48)%mod;ch=getchar();}
return x*f;
}
long long n,m,cnt;
long long a[1000010],ans[1000010];
bool check(long long x)
{
long long ans=0;
for(int i=n;i>=1;i--)
ans=(ans+a[i])*x%mod;
ans=(ans+a[0])%mod;
if(ans==0)
return true;
return false;
}
int main()
{
bool flag=false;
n=read();m=read();
for(int i=0;i<=n;i++)
a[i]=read();
for(int i=1;i<=m;i++)
{
if(check(i))
{
ans[++cnt]=i;
flag=true;
}
}
if(!flag)
{
puts("0");
return 0;
}
cout<<cnt<<endl;
for(int i=1;i<=cnt;i++)
printf("%lld\n",ans[i]);
return 0;
}
posted on 2020-12-06 18:44 DestinHistoire 阅读(106) 评论(0) 收藏 举报