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 }