题目描述Description
输入描述 Input Description
输入共n+2行。
第一行包含2个整数n、m,每两个整数之间用一个空格隔开。
接下来的n+1行每行包含一个整数,依次为a0,a1,a2,……,an。
输出描述 Output Description
输出文件名为equation.out。
第一行输出方程在[1, m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。
样例输入 Sample Input
2 10
1
-2
1
样例输出 Sample Output
1
1
数据范围及提示 Data Size & Hint
NOIP 2014 的压轴题qwq,求方程的解,因为 n <= 100 所以说不能用求根公式来解只能暴力遍历 1 到 m 。
直接读入 a[i] 后暴力找根即可得到30分,100分的算法,观察方程可以发现 f(x) %p == f(x+p) %p 所以说只要处理出0 到 p-1 的根然后筛掉不合法的解就好了,为了存下数,要对 a[i] 取模,因为模的数较小不能保证正确性,所以要多模几个。
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
char in[100010];
ll num[101][5];
int n,m;
ll mod[5] = {10657,10007,10739,11329,11149};
bool fin[1001000][5];
int ans[1000010];
int main()
{
scanf("%d%d",&n,&m);
for(int i = 0 ; i <= n ; i ++)
{
scanf("%s",in);
int l = strlen(in);
bool flag = 1;
for(int j = 0 ; j < l ; j ++)
{
if(in[j] == '-')
flag = 0;
else
for(int k = 0 ; k <= 4 ; k ++)
num[i][k] = (num[i][k] * 10 + in[j] - '0') % mod[k];
}
if(!flag)
for(int k = 0 ; k <= 4 ; k ++)
num[i][k] = -num[i][k];
}
for(int k = 0 ; k <= 4 ; k ++)
{
for(int i = 0 ; i < mod[k] ; i ++)
{
ll temp = 0;
for(int j = n ; j >= 0 ; j --)
temp = (temp * i + num[j][k]) % mod[k];
if(temp == 0)
fin[i][k] = 1;
}
}
for(int i = 1 ; i <= m ; i ++)
{
bool flag = 1;
for(int k = 0 ; k <= 4 ; k ++)
{
if(!fin[i%mod[k]][k])
{
flag = 0;
break;
}
}
if(flag)
ans[++ ans[0]] = i;
}
cout<<ans[0]<<endl;
for(int i = 1 ; i <= ans[0] ; i ++)
cout<<ans[i]<<endl;
return 0;
}
//g++ 解方程.cpp -o 解方程.exe