[NOIP2014] 解方程&加强版 (BZOJ3751 & VIJOS1915)
大概有$O(m)$,$O(n\sqrt{nm})$,$O(n\sqrt{m})$的3个算法,其中后2个可以过加强版。代码是算法3,注意BZOJ的数据卡掉了小于20000的质数。
#include<algorithm> #include<cstdio> using std::sort; typedef long long ll; const int p1=20123; const int p2=20201; const int p3=2e8-9; char z[10002]; typedef int arr[1001]; arr f1,f2,f3,s1,s2,s3; int n,m,n1,n2,n3; int eval(int x,int*f,int p){ ll s=0; for(int i=n;~i;--i) s=(s*x+f[i])%p; return s; } void up(int&s,int t,int p){ s=(s*10ll+t-48)%p; } int inv(int t,int p){ int s=1; for(int n=p-2;n;n>>=1){ if(n&1)s=s*t%p; if(n>1)t=t*t%p; } return s; } const ll q1=p2*inv(p2,p1); const ll q2=p1*inv(p1,p2); const int p0=p1*p2; int main(){ scanf("%d%d",&n,&m); for(int i=0;i<=n;++i){ scanf("%s",z); for(int j=*z=='-';z[j];++j){ up(f1[i],z[j],p1); up(f2[i],z[j],p2); up(f3[i],z[j],p3); } if(*z=='-'){ f1[i]=p1-f1[i]; f2[i]=p2-f2[i]; f3[i]=p3-f3[i]; } } for(int i=0;i<p1;++i) if(!eval(i,f1,p1))s1[n1++]=i; for(int i=0;i<p2;++i) if(!eval(i,f2,p2))s2[n2++]=i; for(int i=0;i<n1;++i) for(int j=0;j<n2;++j){ int x=(s1[i]*q1+s2[j]*q2)%p0; if(1<=x&&x<=m) if(!eval(x,f3,p3))s3[n3++]=x; } printf("%d\n",n3); sort(s3,s3+n3); for(int i=0;i<n3;++i) printf("%d\n",s3[i]); }