Luogu P5205 模板 多項式開根

2022-05-20 17:06:40 字數 2355 閱讀 8053

給定乙個 \(n-1​\) 次多項式 \(a(x)​\),求乙個在\(\bmod x^n​\)意義下的多項式 \(b(x)​\),使得 \(b^2(x) \equiv a(x)(\bmod x^n)​\)

多項式的係數在 \(\bmod\ 998244353​\) 的意義下進行運算。

\(n \leq 10^5,a_i \in [0,998244352] \cap \mathbb\)

其實推導過程和多項式求逆類似

考慮倍增

假設我們已經求出了乙個多項式 \(g(x)\) 使得 \(g^2(x) \equiv a(x) \ (\bmod\ x^\rceil})\) ,而 \(b(x)\) 本來就有 \(b^2(x) \equiv a(x) \ (\bmod\ x^\rceil})\) ,那麼

\[b^2(x)-g^2(x)\equiv 0(\bmod x^\rceil})\tag

\]平方差公式展開

\[(b(x)-g(x))(b(x)+g(x))\equiv 0(\bmod x^\rceil})\tag

\]在這裡我們需要說一下究竟取哪個,又有什麼區別的問題

假設題目要求的最終的答案為 \(f(x)\)

因為是在模大質數意義下進行的運算,所以要麼有 \(b(x)\equiv g(x)(\bmod x^\rceil})\) ,要麼有 \(b(x)+g(x)\equiv 0(\bmod x^\rceil})\) ,至於為什麼只需要關注一下 \(0\) 次項的係數就可以了

若我們在倍增的過程中全部選擇 \(b(x)\equiv g(x)(\bmod x^\rceil})\) 或選擇了偶數次 \(b(x)+g(x)\equiv 0(\bmod x^\rceil})\) ,那麼最後得到的答案就是 \(f(x)\),反之若我們選擇了奇數次 \(b(x)+g(x)\equiv 0(\bmod x^\rceil})\) ,那麼最後得到的答案就是 \(-f(x)\) ,原因在下面的推導中不難看出。所以 \(\sqrt\) 有兩解,為 \(\pm f(x)\)

我們選擇前者,即

\[b(x) \equiv g(x) \ (\bmod x^\rceil})\tag

\]移項後平方展開得到

\[b^2(x)-2b(x)g(x)+g^2(x)\equiv 0(\bmod x^n)\tag\]即

\[a(x)-2b(x)g(x)+g^2(x)\equiv 0(\bmod x^n)\tag

\]移項得

\[2b(x)g(x)\equiv a(x)+g^2(x)(\bmod x^n)\tag

\]然後除過去,得

\[b(x)\equiv \frac(\bmod x^n)\tag

\]多項式求逆+\(\text\)即可

#include#includeusing namespace std;

const int n=1e5+10;

const int mod=998244353;

const int g=3;

const int invg=332748118;

int n,a[n<<2],b[n<<2],c[n<<2],d[n<<2],f[n<<2],h[n<<2],k;

inline void add(int &x,int y)

inline int mod(int x)

inline int fas(int x,int p)return res;}

inline void ntt(int *a,int f)

for(register int i=1;i>1;pinv(a,b,m);

k=1;while(k<=deg+deg-2)k<<=1;int inv=fas(k,mod-2);

for(register int i=0;i>1;sqrt(a,b,m);

k=1;while(k<=deg+deg-2)k<<=1;int inv=fas(k,mod-2);

for(register int i=0;ifor(register int i=deg;intt(c,1);

for(register int i=0;intt(c,-1);

for(register int i=0;ifor(register int i=deg;ifor(register int i=0;ifor(register int i=0;ifor(register int i=deg;ifor(register int i=0;ipinv(d,f,deg);

k=1;while(k<=deg+deg-2)k<<=1;

ntt(f,1);ntt(c,1);

for(register int i=0;intt(b,-1);

for(register int i=0;ifor(register int i=deg;i}int main()

洛谷5205 模板 多項式開根

點此看題面 大致題意 給定多項式 f x 求 g x 滿足 g x 2 equiv f x mod x n 向 998244353 取模。在知道多項式乘法逆的前提下,這道題的推導其實是非常簡單,甚至要簡單於多項式乘法逆的。但由於多項式開根最後的求解依然需要用到多項式乘法逆,所以總體難度還是高於多項式...

洛谷P5205 模板 多項式開根

題目大意 給你 n 項多項式 a x 求出 b x 滿足 b 2 x equiv a x pmod 題解 考慮已經求出 b 0 x 滿足 b 0 2 x equiv a x pmod b x b 0 x equiv0 pmod b 2 x 2b x b 0 x b 0 2 x 0 pmod a x ...

多項式模板

檢查資料 input 61 2 3 4 5 6 1.ntt多項式求逆 include define maxn 2100005 define ll long long define mod 998244353 using namespace std int lg maxn r maxn w maxn ...