Description
已知多项式方程:
a0+a1*x+a2*x^2+...+an*x^n=0
求这个方程在[1,m]内的整数解(n和m均为正整数)。
Input
第一行包含2个整数n、m,每两个整数之间用一个空格隔开。
接下来的n+1行每行包含一个整数,依次为a0,a1,a2,...,an。
Output
第一行输出方程在[1,m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1,m]内的一个整数解。
Sample Input
2 10
2
-3
1
Sample Output
2
1
2
HINT
对于100%的数据,0<n≤100,|ai|≤,an≠0,m≤1000000。
这道题显然不可以用暴力解决(因为在计算过程中会用到高精乘,最优时间复杂度为O()(L为长度),显然会T),所以考虑一种玄妙的做法,对于,将两边同时取模,即,这个方程的解一定包含前一个方程的解,且有极大的可能两者的解相同,所以只需要求解后一个方程即可,但此时的时间复杂度为O(),仍然会T,所以我们考虑一个性质,由于这个性质,我们只需要考虑0~P-1之间是否有解即可,但当P很大时,时间复杂度并没有得到优化,所以我们可以选择10000~50000之间的数,同时为了保证最后结果的正确性,可以在时间允许范围内选择多个质数作为P,最终时间复杂度为O(),下面是程序:
#include<stdio.h>
#include<map>
#include<iostream>
using namespace std;
const int p[10]={30011,11261,14843,19997,10007,21893};
int t[1000005],a[105][10],ans[1000005],n,m;
void read(int *s){
int i;
bool f=0;
char c=getchar();
for(i=0;i<6;i++){
s[i]=0;
}
while((c<'0'||c>'9')&&c!='-'){
c=getchar();
}
if(c=='-'){
f=1;
c=getchar();
}
while(c>='0'&&c<='9'){
for(i=0;i<6;i++){
s[i]=(s[i]*10+c-'0')%p[i];
}
c=getchar();
}
if(f){
for(i=0;i<6;i++){
s[i]*=-1;
}
}
}
bool check(int x,int k){
int i,s=a[n][k];
for(i=n-1;i>=0;--i){
s=(s*x+a[i][k])%p[k];
}
return !s;
}
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
for(i=0;i<=n;i++){
read(a[i]);
}
for(i=0;i<6;i++){
for(j=0;j<p[i];j++){
if(check(j,i)){
for(k=j;k<=m;k+=p[i]){
t[k]++;
}
}
}
}
for(i=1,k=0;i<=m;i++){
if(t[i]==6){
ans[++k]=i;
}
}
printf("%d\n",k);
for(i=1;i<=k;i++){
printf("%d\n",ans[i]);
}
return 0;
}