luogu P2312 解方程

已知多项式方程:$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)$

然后可以多找几个素数一块计算了……

 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 }
luogu P2312 解方程

 

转载于:https://www.cnblogs.com/KingSann/articles/9593023.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值