已知多项式方程:$a_0+a_1x+a_2x^2+ \cdots +a+nx^n=0$
求这个方程在 $[1,m]$ 内的整数解($n和m$ 均为正整数)
对于 $100\%$ 的数据:$0<n \le 100, \mid a_i \mid \le 10^{10000},a_n \not= 0,m<10^6$
不看题解不会做系列
首先秦九昭算法是这么讲述的:$a_0+a_1x+a_2x^2+ \dots + a_nx^n=x(x(x( \cdots xa_n + a_{n-1} \cdots + a_3 )+a_2)+a_1) + a_0$
也就是说如果系数数组为$a$,下标从$0 \sim n$,那么可以这么计算$f(x)$:
ll f(ll x) { ll res = 0; for(int i = n ; ~ i ; -- i) { res = x * (res + a[i]); } return res; }
于是就可以$O(n)$的计算$f(x)$了
然而这些系数都是高精度……
在模$p$意义下有这样十分显然的结论:
1. 如果$f(x) = 0$,那么$f(x+kp) = 0$
2. 如果$f(x) \not= 0$,那么$f(x+kp) \not= 0$
于是如果$f(x) \not= 0$,那么可以不再计算$f(x + kp)$
然后可以多找几个素数一块计算了……
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N = 1e6 + 10, p[3] = { 998244353, 23333, 2333 }; 5 char s[N]; 6 int a[N], b[N], c[N], vis[N], ans[N], tot, n, m; 7 int calc(int v) { 8 int x = 0, y = 0, z = 0; 9 for(int i = n ; ~ i ; -- i) { 10 x = ((ll) v * (a[i] + x)) % p[0]; 11 y = ((ll) v * (b[i] + y)) % p[1]; 12 z = ((ll) v * (c[i] + z)) % p[2]; 13 } 14 if(x) for(int j = v ; j <= m ; j += p[0]) vis[j] = 1; 15 if(y) for(int j = v ; j <= m ; j += p[1]) vis[j] = 1; 16 if(z) for(int j = v ; j <= m ; j += p[2]) vis[j] = 1; 17 return x || y || z; 18 } 19 20 int main() { 21 scanf("%d%d", &n, &m); 22 for(int i = 0 ; i <= n ; ++ i) { 23 scanf("%s", s + 1); 24 int sig = s[1] == '-'; 25 for(int j = sig + 1 ; s[j] ; ++ j) { 26 a[i] = ((ll) a[i] * 10 + s[j] - '0') % p[0]; 27 b[i] = ((ll) b[i] * 10 + s[j] - '0') % p[1]; 28 c[i] = ((ll) c[i] * 10 + s[j] - '0') % p[2]; 29 } 30 if(sig) { 31 a[i] = (p[0] - a[i]) % p[0]; 32 b[i] = (p[1] - b[i]) % p[1]; 33 c[i] = (p[2] - c[i]) % p[2]; 34 } 35 } 36 for(int i = 1 ; i <= m ; ++ i) { 37 if(!vis[i] && !calc(i)) 38 ans[++ tot] = i; 39 } 40 printf("%d\n", tot); 41 for(int i = 1 ; i <= tot ; ++ i) { 42 printf("%d\n", ans[i]); 43 } 44 }