题目描述

已知多项式方程:

a0+a1x+a2x^2+..+anx^n=0

求这个方程在[1, m ] 内的整数解(n 和m 均为正整数)

输入输出格式

输入格式:
输入文件名为equation .in。

输入共n + 2 行。

第一行包含2 个整数n 、m ,每两个整数之间用一个空格隔开。

接下来的n+1 行每行包含一个整数,依次为a0,a1,a2..an

输出格式:
输出文件名为equation .out 。

第一行输出方程在[1, m ] 内的整数解的个数。

接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m ] 内的一个整数解。

输入输出样例

输入样例#1:
2 10
1
-2
1
输出样例#1:
1
1
输入样例#2:
2 10
2
-3
1
输出样例#2:
2
1
2
输入样例#3:
2 10
1
3
2

输出样例#3:
0
说明

30%:0 < n<=2,|ai|<=100,an!=0,m<100

50%:0 < n<=100,|ai|<=10^100,an!=0,m<100

70%:0 < n<=100,|ai|<=10^10000,an!=0,m<10000

100%:0 < n<=100,|ai|<=10^10000,an!=0,m<1000000


【分析】
好神奇啊
玄学取mod大法
如果我们模的数字是k。左边式子带入x和带入x+k是没有区别的。如果我们把质数k取得小一些,这样x就不用试1~m,而是试1~k。这样复杂度就变成了O(nkprime),如果k取10^4左右就完全没有问题。


【代码】

//NOIP 2014 解方程 
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
int n,m;
int mod[6]={0,22861,22871,22877,22901,22907};
int dp[105][10]; //就是爱把变量名设为dp
int ans[1000005];
int main()
{
int i,j,k;
scanf("%d%d",&n,&m);
fo(i,0,n)
{
int mul=1,st=0;
char ch[10005];
scanf("%s",ch);
int len=strlen(ch)-1;
if(ch[0]=='-') mul=-1,st++;
fo(j,st,len)
fo(k,1,5)
dp[i][k]=(dp[i][k]*10+ch[j]-'0')%mod[k];
fo(k,1,5) dp[i][k]*=mul;
}
bool flag[1000005];
memset(flag,1,sizeof flag);
fo(i,1,m) //枚举解
if(flag[i])
{
bool root=1;
for(j=1;root && j<=5;j++)
{
ll val=dp[0][j],x=i%mod[j];
fo(k,1,n)
{
val=(val+dp[k][j]*x%mod[j])%mod[j];
x=i*x%mod[j]; //递推x^k
}
if(val)
{
root=0;
for(k=i;k<=m;k+=mod[j])
flag[k]=0;
}
}
if(root) ans[++ans[0]]=i;
}
fo(i,0,ans[0]) printf("%d\n",ans[i]);
return 0;
}