描述
已知多项式方程:
a0+a1x+a2x2+...+anxn=0
求这个方程在[1, m]内的整数解(n 和 m 均为正整数)。
格式
输入格式
输入共 n+2 行。
第一行包含 2 个整数 n、m,每两个整数之间用一个空格隔开。
接下来的 n+1 行每行包含一个整数,依次为
a0,a1,a2,...,an
。
输出格式
第一行输出方程在[1, m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。
限制
对于 30%的数据,0 < n ≤ 2,
|ai|
≤ 100,
an
≠ 0, m ≤ 100;
对于 50%的数据,0 < n ≤ 100,
|ai|
≤
10100
,
an
≠ 0,m ≤ 100;
对于 70%的数据,0 < n ≤ 100,
|ai|
≤
1010000
,
an
≠ 0,m ≤ 10000;
对于 100%的数据,0 < n ≤ 100,
|ai|
≤
1010000
,
an
≠ 0,m ≤ 1000000。
老师讲了一种奇怪的孙子定理方法,没有听懂
然后看了hzwer的程序:
因为系数很大,肯定得用高精度
但是可以
我们可以假设 f(x)%a=0 则x
f(x+a)也可以
所以就好啦
#include<iostream>
#include<cstdio>
using namespace std;
const int p[]={11261,19997,22877,21893,14843};
int n,m;
int a[1000010],used[1000010];
string s[10010];
int f(int x,int p)
{
int sum=0;
for(int i=n;i>=0;i--)
{
sum*=x;
sum%=p;
sum+=a[i];
sum%=p;
}
return sum%p;
}
int calc(string s,int p)
{
int num=0;
int f=1;
for(int i=0;i<s.length();i++)
{
if(s[i]=='-')
{
f=-1;
continue;
}
num*=10;
num%=p;
num+=s[i]-'0';
num%=p;
}
num*=f;
return num%p;
}
void mod(int p)
{
for(int i=0;i<=n;i++)
{
a[i]=calc(s[i],p);
}
for(int i=1;i<p;i++)
if(f(i,p)%p!=0)
for(int j=0;j*p+i<=m;j++)
{
if(!used[j*p+i])used[0]--;
used[j*p+i]=1;
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<=n;i++)
cin>>s[i];
used[0]=m;
for(int i=0;i<5;i++)
mod(p[i]);
printf("%d\n",used[0]);
for(int i=1;i<=m;i++)
{
if(!used[i])
printf("%d\n",i);
}
return 0;
}