[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_2\ldots a_n$ 。
第一行輸出方程在 $[1,m]$ 內的整數解的個數。
接下來每行一個整數,按照從小到大的順序依次輸出方程在 $[1,m]$ 內的一個整數解。
輸入輸出樣例
輸入樣例#1:2 10 1 -2 1輸出樣例#1:
1 1輸入樣例#2:
2 10 2 -3 1輸出樣例#2:
2 1 2輸入樣例#3:
2 10 1 3 2輸出樣例#3:
0
說明
對於 $30\%$ 的數據: $0<n\le 2,|a_i|\le 100,a_n≠0,m<100$ 。
對於 $50\%$ 的數據: $0<n\le 100,|a_i|\le 10^{100},a_n≠0,m<100$ 。
對於 $70\%$ 的數據: $0<n\le 100,|a_i|\le 10^{10000},a_n≠0,m<10^4$ 。
對於 $100\%$ 的數據: $0<n\le 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\n", cnt); for (reg int i = 1 ; i <= cnt ; i ++) printf("%lld\n", ans[i]); return 0; }
[Noip2014] 解方程