[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]);
}
posted @ 2016-05-15 21:05  f321dd  阅读(215)  评论(0编辑  收藏  举报