NOIP2014 解方程
Description
Input
输入文件名为equation.in。
输入共n+2行。
第一行包含2个整数n、m,每两个整数之间用一个空格隔开。
接下来的n+1行每行包含一个整数,依次为a0,a1,a2,……,an。
Output
输出文件名为equation.out。
第一行输出方程在[1, m]内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在[1, m]内的一个整数解。
Sample Input
输入样例#1:
2 10
1
-2
1
输入样例#2:
2 10
2
-3
1
输入样例#3:
2 10
1
3
2
Sample Output
输出样例#1:
1
1
输出样例#2:
2
1
2
输出样例#3:
0
Hint
Solution:
这题什么鬼,看到解方程还是第三题直接吓尿好吧...
感觉哈希比较像正解。然而害怕并不是很靠谱,于是敲完了30%的long long和50%的高精,就写了个哈希放在了那里,测了一下极限数据都快要三秒了,于是就加上了双哈希。(233)
然而正解真的是哈希…(这么玄学真的好吗)
对于 f(x)%P=0 ,我们认为 f(x)=0 的可能性是非常大的,然后注意到式子里只有加法与幂运算:如果 xn≡0(modP) ,则 (x+P)n≡0(modP) 。则如果 f(x)≡0(modP) ,有 f(x+P)≡0(modP) 。
于是取几个小素数
P
,计算出
当然如果不放心,可以再用一个大素数依次检验一下筛选出来的数。
#include<ctime>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#define ll long long
#define mp make_pair
#define pb push_back
#define pll pair<ll,ll>
#define pii pair<int,int>
#define lson (p<<1)
#define rson (p<<1|1)
#define lowbit(x) (x&(-x))
#define siz(x) ((x).size())
using namespace std;
const int M=105;
const int Len=20005;
int n,m;
int f[5]={9227,10007,10009,9281,7741};
char str[Len];
int A[5][M],rs[5][Len],Ans[1000005],sz;
int calc(int x,int i){
int x0=1,sum=0;
for(int j=0;j<=n;j++){
sum=(sum+x0*A[i][j])%f[i];
x0=x0*x%f[i];
}
return sum;
}
bool check(int x){
for(int i=0;i<5;i++)
if(rs[i][x%f[i]]!=0)return false;
return true;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<=n;i++){
scanf("%s",str+1);
int len=strlen(str+1);
for(int j=0;j<5;j++){
int k=1;
if(str[k]=='-')k++;
for(;k<=len;k++){
A[j][i]=(A[j][i]*10+(str[k]^48))%f[j];
}
if(str[1]=='-')A[j][i]=-A[j][i];
}
}
for(int i=0;i<5;i++)
for(int j=0;j<f[i];j++)
rs[i][j]=calc(j,i);
for(int i=1;i<=m;i++)
if(check(i))Ans[++sz]=i;
printf("%d\n",sz);
for(int i=1;i<=sz;i++)
printf("%d\n",Ans[i]);
return 0;
}