NOIP2014 bzoj3751 Day2T3 解方程 数学&hash


       NOIP2014的最后一题,本来要在NOIP2015前做好的,现在终于把坑填上了。

       bzoj上的数据似乎经过加强了?质数不取大似乎过不掉。

       真想不明白我初二的时候看到这道题目是怎么在5s内想到去取一个模的(当然不是在考场而是在家里)

       显然,若f(x)=0,则f(x)≡f(x0)≡0(mod p),其中x≡x0(0<=x0<p)。那么如果f(x0)≡0(mod p),那么基本可以确定f(x)=0。当然如果不用p取模的话输入早就爆掉了。。那么如果p比较大的话,比如>m,那么取一个质数,基本上出错概率就很小了。

       但是这么做是无法拿到满分的,而且出错概率也比较大。如果换用若干个较小的质数,比如说10^4级别的,就能满分的。这里我取了7个15000~35000的质数,是程序随机化跑出来的。实测如果去10个10000左右的质数,而且质数比较接近的话会直接OLE(看样子质数太接近会导致出错概率很大),如果取10个又会超时。之所以不往大的取是因为50000*50000>2^31,就要开long long了会减慢速度。然后读入的时候一边读入一边取模就行了。

       似乎并没有什么高科技的东西??感觉只要想到取模就基本上能AC了。

       当然对于ccf那么水的数据,6,7个10000左右质数的似乎就能过去了?

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;

int n,m,a[10][1005],sum[1000005];
char ch[20005];
const int prm[7]={15259,26833,25889,19249,26681,21517,21739};
int main(){
	scanf("%d%d",&n,&m); int i,j,k;
	for (i=0; i<=n; i++){
		scanf("%s",ch+1); int len=strlen(ch+1),p=1;
		if (ch[1]=='-'){ ch[1]='0'; p=-1; }
		for (j=0; j<7; j++){
			for (k=1; k<=len; k++) a[j][i]=(a[j][i]*10+ch[k]-'0')%prm[j];
			a[j][i]=p*a[j][i]%prm[j];
		}
	}
	for (i=0; i<7; i++)
		for (j=0; j<prm[i]; j++){
			int x=a[i][n];
			for (k=n-1; k>=0; k--) x=(x*j+a[i][k])%prm[i];
			if (!x) for (k=j; k<=m; k+=prm[i]) sum[k]++;
		}
	int ans=0; for (i=1; i<=m; i++) if (sum[i]==7) ans++;
	printf("%d\n",ans); for (i=1; i<=m; i++) if (sum[i]==7) printf("%d\n",i);
	return 0;
}

by lych

2015.12.24

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告