LOJ2503 NOIP2014 解方程 【HASH】

版权声明:欢迎转载,请注明出处,谢谢 https://blog.csdn.net/Dream_maker_yk/article/details/82666693

LOJ2503 NOIP2014 解方程


LINK


题目大意就是给你一个方程,让你求 [ 1 , m ] [1,m] 中的解,其中系数非常大


看到是提高T3还是解方程就以为是神仙数学题

后来研究了一下高精之类的算法发现过不了多少分

后面佬说这题是hash

然后就


考虑对于一个式子 f ( x ) = 0 f(x)=0 肯定会满足 f ( x ) % p r i m e = 0 f(x)\%prime=0
所以我们直接多取几个相近的prime,减小冲突几率

然后我们只需要预处理每个系数对于每个prime的模数,然后判断一下就可以了

但是这样会TLE

又可以发现对于任意的 f ( x ) % p r i m e = 0 f(x)\%prime=0 ,等价于 f ( x % p r i m e ) % p r i m e = 0 f(x\%prime)\%prime=0
所以对于每个质数直接枚举比它小的数进行检查就好了

然后就比较和谐了

扫描二维码关注公众号,回复: 3258896 查看本文章

中间出了一些比较玄学的错误导致交了很多个70分
不过问题不大


#include<bits/stdc++.h>
using namespace std;
#define N 110
#define M 1000010
int prime[5]={10099,10103,10111,10133,10139};
int pa[N][5],n,m;
char c[M];
bool vis[M],ak[M][5];
int check(int x,int id){
	int pic=0;
	for(int i=n;i>=0;i--)
		pic=(pic*x%prime[id]+pa[i][id])%prime[id];
	return pic;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<=n;i++){
		scanf("%s",c);
		int len=strlen(c),j=0;
		if(c[0]=='-')j++;
		for(;j<len;j++)for(int k=0;k<5;k++)
			pa[i][k]=(pa[i][k]*10+c[j]-'0')%prime[k];
		if(c[0]=='-')for(int k=0;k<5;k++)pa[i][k]*=-1;
	}
	int cnt=0;
	for(int j=0;j<5;j++)
		for(int i=0;i<prime[j];i++)
			if(check(i,j)!=0)ak[i][j]=1;
	for(int i=1;i<=m;i++){
		bool can=1;
		for(int j=0;j<5;j++)if(ak[i%prime[j]][j]){can=0;break;}
		if(can)vis[i]=1,cnt++;
	}
	printf("%d\n",cnt);
	for(int i=1;i<=m;i++)if(vis[i])printf("%d\n",i);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_maker_yk/article/details/82666693
今日推荐