[Noip2014] 解方程
Posted brimon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Noip2014] 解方程相关的知识,希望对你有一定的参考价值。
题目描述
已知多项式方程: $$a_0+a_1x+a_2x^2+cdots+a_nx^n=0$$
求这个方程在 $[1,m]$ 内的整数解( $n$ 和 $m$ 均为正整数)。
输入输出格式
输入格式:输入共 $n + 2$ 行。
第一行包含 $2$ 个整数 $n, m$ ,每两个整数之间用一个空格隔开。
接下来的 $n+1$ 行每行包含一个整数,依次为 $a_0,a_1,a_2ldots a_n$ 。
第一行输出方程在 $[1,m]$ 内的整数解的个数。
接下来每行一个整数,按照从小到大的顺序依次输出方程在 $[1,m]$ 内的一个整数解。
输入输出样例
2 10 1 -2 1
1 1
2 10 2 -3 1
2 1 2
2 10 1 3 2
0
说明
对于 $30\%$ 的数据: $0<nle 2,|a_i|le 100,a_n≠0,m<100$ 。
对于 $50\%$ 的数据: $0<nle 100,|a_i|le 10^{100},a_n≠0,m<100$ 。
对于 $70\%$ 的数据: $0<nle 100,|a_i|le 10^{10000},a_n≠0,m<10^4$ 。
对于 $100\%$ 的数据: $0<nle 100,|a_i|le 10^{10000},a_n≠0,m<10^6$ 。
疯狂加美元符结果都没有用好伤心啊。
一看数据范围就知道这题一般的算法做不出来,这数据范围高精度过不去...
挣扎了一下午无望然后膜拜题解。
wao!这太神了。
这题要我在考场上绝对想不出来。
谁脑洞这么大想出取模的方法啊233了。
先把输入的$large ai$对一个素数取模然后用秦九韶算。
我们设原函数为$large f[]$。
那么$large f[x]%p=0%p=0$。
所以取一个素数当模数就行了。
然而50分。
因为以上的算法冲突的概率是很大的, 解决方法就是多取几个模数。
然后70,剩下的TLE。
如何解决?
我们考虑,$large f[x]%p!=0, f[x*k+b]%k!=0$.
所以我们只需要求出1~mod-1的答案就行了。
#include <iostream> #include <cstdio> #include <string> #include <cstring> using namespace std; #define reg register #define ll long long #define int long long int n, m; int a[105][3]; bool can[1000004][3]; int p[3] = {23333, 23537, 15733}; char ch[10005]; int ans[1000005], cnt; signed main() { scanf("%lld%lld", &n, &m); for (reg int i = 0 ; i <= n ; i ++) { memset(ch, 0, sizeof ch); scanf("%s", ch + 1); int len = strlen(ch + 1); int tmp[3] = {0}, fu = 1; int j = 1; if (ch[1] == ‘-‘) fu = -1, j = 2; for (j ; j <= len ; j ++) for (reg int k = 0 ; k <= 2 ; k ++) tmp[k] = (tmp[k] * 10 + ch[j] - ‘0‘) % p[k]; for (reg int k = 0 ; k <= 2 ; k ++) { a[i][k] = tmp[k]; if (fu == -1) a[i][k] = p[k] - a[i][k]; } } for (reg int i = 0 ; i <= mod ; i ++) { for (reg int k = 0 ; k <= 2 ; k ++) { ll sum = a[n][k]; for (reg int j = n - 1 ; j >= 0 ; j --) sum = ((a[j][k] + sum * i) % p[k] + p[k]) % p[k]; if (!sum) can[i][k] = 1; } } for (reg int i = 1 ; i <= m ; i ++) { for (reg int k = 0 ; k <= 2 ; k ++) if (!can[i%p[k]][k]) goto End; ans[++cnt] = i; End:; } printf("%lld ", cnt); for (reg int i = 1 ; i <= cnt ; i ++) printf("%lld ", ans[i]); return 0; }
以上是关于[Noip2014] 解方程的主要内容,如果未能解决你的问题,请参考以下文章