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;
}
2015.12.24