luogu2312 [NOIp2015]解方程 (秦九韶)

秦九韶算法:多项式$a_0+a_1x+a_2x^2+...+a_nx^n=a_0+x(a_1+x(a_2+...+(xa_n))..)$,这样对于一个x,可以在O(n)求出结果

为了避免高精度,我们同时模几个质数来判断每个的值是不是等于0,这样出锅的概率就非常小

然而这样做复杂度是O(nm),过不去

我们发现对于某一个模数p,x+kp和x算出来的结果模p以后是一样的,这样的话,只要先算出来一个比较小的p以内的所有结果,再去从那些里挑出模p等于0的,再去判断这些+kp以后模别的等不等于0,这样复杂度就会减小很多

我选择了13331,19260817和1e9+7

另外快读也需要修改一下

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=110,maxm=1e6+10;
 7 const int p[3]={13331,19260817,1e9+7};
 8 
 9 inline void rd(int &x1,int &x2,int &x3){
10     x1=x2=x3=0;char c=getchar();int neg=1;
11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
12     while(c>='0'&&c<='9'){
13         x1=(x1*10+c-'0')%p[0];
14         x2=(x2*10+c-'0')%p[1];
15         x3=(x3*10ll+c-'0')%p[2];
16         c=getchar();
17     }x1=x1*neg%p[0];
18     x2=x2*neg%p[1];
19     x3=x3*neg%p[2];
20 }
21 
22 int N,M,a[maxn][3],cnt;
23 queue<int> q;
24 bool ans[maxm];
25 
26 bool judge(int id,int x){
27     int sum=a[N][id];x%=p[id];
28     for(int i=N;i;i--) sum=((ll)sum*x+a[i-1][id])%p[id];
29     return sum==0;
30 }
31 
32 int main(){
33     // freopen("testdata.in","r",stdin);
34     int i,j,k;
35     scanf("%d%d",&N,&M);
36     for(i=0;i<=N;i++) rd(a[i][0],a[i][1],a[i][2]);
37     for(i=1;i<=min(M,p[0]);i++){
38         if(judge(0,i)) q.push(i%p[0]);
39     }
40     while(!q.empty()){
41         int x=q.front();q.pop();
42         for(int i=0;x+p[0]*i<=M;i++){
43             if(judge(1,x+p[0]*i)&&judge(2,x+p[0]*i)) ans[x+p[0]*i]=1,cnt++;
44         }
45     }
46     printf("%d\n",cnt);
47     for(i=1;i<=M;i++) if(ans[i]) printf("%d\n",i);
48     
49     return 0;
50 }

 

posted @ 2018-09-25 21:23  Ressed  阅读(183)  评论(0编辑  收藏  举报