【hash】BZOJ3751-[NOIP2014]解方程
【题目大意】
已知多项式方程:a0+a1*x+a2*x^2+...+an*x^n=0。求这个方程在[1,m]内的整数解(n和m均为正整数)。
【思路】
*当年考场上怒打300+行高精度,然而没骗到多少orz 然而正解只有60+行
[前铺]f(n) mod p=f(n mod p) mod p
取四个素数,分别对每个ai取模。先预处理x=0..p-1的情况,直接代入多项式计算即可。再在O(m)时间内检验1..m,对于≥p的利用前铺公式可得。如果模四个素数结果均能得到0,说明这个数是方程的解。
P.S.这个的前提是你的脸好……我一开始随便取的四个就WA了QAQ
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=100+5; 4 const int MAXM=1000000+5; 5 const int MAXP=30000; 6 typedef long long ll; 7 int prime[4]={17389,22349,22367,22369}; 8 int n,m,a[MAXN],hash[MAXN][4],table[MAXP][4],ans[MAXM],cnt=0; 9 10 ll get_table(int j,int x) 11 { 12 ll ret=0; 13 for (int i=n;i>=0;i--) 14 ret=(ret*x+hash[i][j])%prime[j]; 15 return ret; 16 } 17 18 int read(int x) 19 { 20 char str[10010]; 21 scanf("%s",str); 22 int negative=0; 23 for (int i=0;str[i];i++) 24 { 25 if (str[i]=='-') negative=1; 26 else for (int j=0;j<4;j++) 27 hash[x][j]=((hash[x][j]*10)%prime[j]+(str[i]-'0'))%prime[j]; 28 } 29 if (negative) 30 for (int j=0;j<4;j++) 31 hash[x][j]=(prime[j]-hash[x][j])%prime[j]; 32 } 33 34 void init() 35 { 36 memset(hash,0,sizeof(hash)); 37 scanf("%d%d",&n,&m); 38 for (int i=0;i<=n;i++) read(i); 39 for (int i=0;i<4;i++) 40 for (int j=0;j<prime[i];j++) table[j][i]=get_table(i,j); 41 } 42 43 void solve() 44 { 45 for (int i=1;i<=m;i++) 46 { 47 int flag=1; 48 for (int j=0;j<4;j++) 49 if (table[i%prime[j]][j]) 50 { 51 flag=0; 52 break; 53 } 54 if (flag) ans[++cnt]=i; 55 } 56 printf("%d\n",cnt); 57 for (int i=1;i<=cnt;i++) printf("%d\n",ans[i]); 58 } 59 60 int main() 61 { 62 init(); 63 solve(); 64 return 0; 65 }