洛谷P5050 模板 多項式多點求值

2022-05-23 22:06:08 字數 3023 閱讀 7661

題目大意:給你乙個$n$次多項式$f(x)$,以及$m$個$x_i$,對於$i\in[1,m]$,求$f(x_i)$

題解:多項式多點求值

令$g(x)=\prod\limits_^m(x-x_i)$,求出$r(x)$使得$f(x)=q(x)\times g(x)+r(x)$。因為當$x=x_i$時,$g(x)=0$,即$f(x)=r(x)$,$f(x)$是$n$次的,$r(x)$是$m-1$次的,似乎可以使得問題縮小了

考慮分治,現在區間為$[l,r]$,令$g_l(x)=\prod\limits_^(x-x_i)$,$g_r(x)=\prod\limits_^r(x-x_i)$,所以$r_l(x)=f(x)\bmod g_l(x)$,$r_r(x)=f(x)\bmod g_r(x)$。最後當$l=r$時,第$i$個的值就是當前$r(x)$的常數項。

那$g(x)$怎麼算呢,分治$fft$,可以先把每個的$g(x)$求出來,用$vector$儲存一下就行了

卡點:不知道為什麼,用$c++$會$mle$,$c++11$就過了,有可能是$vector$初始化部分出鍋了

update(2019-8-1):除法的時候沒有初始化,用的是求逆的初始化,若要使用$\dfrac 32n$優化,需要修改,新的多點求值可看[soj #559]鯤

c++ code:

#include #include #include const int mod = 998244353, g = 3;

namespace math

inline int inv(int x)

}inline void reduce(int &x)

#define maxn 65536

int a[maxn], ans[maxn];

namespace poly

inline void init(const int n)

inline void ntt(int *a, const int op = 1)

}} if (!op) for (register int *i = a; i != a + lim; ++i) *i = static_cast(*i) * ilim % mod;

} std::vectorp[n << 1], s[n << 1];

int c[n], d[n];

void dc_ntt(int rt, int l, int r) ; return ; }

int mid = l + r >> 1;

dc_ntt(rt << 1, l, mid), dc_ntt(rt << 1 | 1, mid + 1, r);

int l = rt << 1, r = rt << 1 | 1;

int n = p[l].size(), m = p[r].size();

init(n + m - 1);

std::copy(p[l].begin(), p[l].end(), c); clear(c + n, c + lim);

std::copy(p[r].begin(), p[r].end(), d); clear(d + m, d + lim);

ntt(c), ntt(d);

for (int i = 0; i < lim; ++i) c[i] = static_cast(c[i]) * d[i] % mod;

ntt(c, 0);

p[rt].assign(c, c + n + m - 1);

} int e[n];

void inv(int *a, int *b, int n)

inv(a, b, n + 1 >> 1);

init(n + n - 1);

std::copy(a, a + n, e); clear(e + n, e + lim);

clear(b + (n + 1 >> 1), b + lim);

ntt(b), ntt(e);

for (int i = 0; i < lim; ++i) b[i] = (2 + mod - static_cast(b[i]) * e[i] % mod) * b[i] % mod;

ntt(b, 0); clear(b + n, b + lim);

} int f[n];

void div(int a, int n, int b, int m)

void __divmod(int res, int a, int n, int b, int m)

div(a, n, b, m);

init(n);

std::reverse_copy(f, f + n - m + 1, c); clear(c + n - m + 1, c + lim);

std::copy(p[b].begin(), p[b].end(), d); clear(d + m, d + lim);

ntt(c), ntt(d);

for (int i = 0; i < lim; ++i) c[i] = static_cast(c[i]) * d[i] % mod;

ntt(c, 0);

for (int i = 0; i < m - 1; ++i) reduce(c[i] = s[a][i] - c[i]);

s[res].assign(c, c + m - 1);

} void divmod(int res, int a)

void solve(int rt, int l, int r)

int mid = l + r >> 1;

divmod(rt << 1, rt), divmod(rt << 1 | 1, rt);

solve(rt << 1, l, mid), solve(rt << 1 | 1, mid + 1, r);

} void work(int *f, int n, int m)

#undef n

}int n, m;

int f[maxn];

int main()

洛谷P4238 模板 多項式求逆

題目傳送門 題目分析 放個板子在blog上,以後複習的時候用。注意每一次呼叫poly rev 的時候都要重新計算一遍rev陣列,而且要先清0。求modxm modx m下的逆元的時候,注意ntt的次數界要開到2m,因為a x g2 x a x g2 x 的次數界加起來為m m2 m 2 2 2m 2...

洛谷 P3803 模板 多項式乘法(FFT)

fft模板題 單向膜拜 從多項式乘法到快速傅利葉變換 fft 學習筆記 大致理解為將多項式從係數表示法轉化為點值表示法然後再變回係數表示法 include include include define n 2621450 define pi acos 1.0 using namespace std ...

洛谷P3803 模板 多項式乘法 NTT

題目傳送門 給定乙個n次多項式f x 和乙個m次多項式g x 請求出f x 和g x 的卷積。輸入格式 第一行2個正整數n,m。接下來一行n 1個數字,從低到高表示f x 的係數。接下來一行m 1個數字,從低到高表示g x 的係數。輸出格式 一行n m 1個數字,從低到高表示f x g x 的係數。...