【LOJ】#150. 挑战多项式
原题链接
多项式全家桶!快乐!(好像少个除法,不过有除法好像不太快乐)
(说真的这是我第一次写exp和开根。。。水平不行。。
从最基础要实现的操作开始吧。。
多项式取模\(x^n\)
这个。。很简单了,把大于等于n指数的系数全改成0就好了
多项式加减法
按位加/减,复杂度\(O(n)\)
多项式求导数
这个的话,选修2-1了解一下?
\((ax^{n})’ = anx^{n - 1}\)
多项式求积分
同上
我们只要求一个多项式的导数是该多项式即可
列个方程可以发现
\(\int ax^{n} = \frac{a}{n + 1}x^{n + 1}\)
多项式乘法
FFT了解一下??不过这题是NTT,复杂度\(O(n \log n)\)
多项式求逆元
也就是\(A(x)B(x) \equiv 1 \pmod{x^{2^{t}}}\)
我们倍增一下,当\(t = 0\)的时候直接求\(\frac{1}{A(0)}\)
如果不是的话有
\(B(x) \equiv G(x) \pmod{x^{2^{t}}}\)
我们把\(G(x)\)移过去
\(B(x) - G(x) \equiv 0 \pmod {x^{2^{t}}}\)
两边平方一下
\((B(x) - G(x))^{2} \equiv 0 \pmod {x^{2^{t + 1}}}\)
\(B(x)^{2} - 2B(x)G(x) + G(x)^{2} \equiv 0 \pmod {x^{2^{t + 1}}}\)
\(B(x)^{2} \equiv 2B(x)G(x) - G(x)^{2} \pmod {x^{2^{t + 1}}}\)
两边同乘一个\(A(x)\)
\(B(x) \equiv 2G(x) - A(x)G(x)^{2} \pmod {x^{2^{t + 1}}}\)
就可以算了
多项式开根
和上面的构造很类似!
\(B(x)^2 = A(x) \pmod{x^{2^{t}}}\)
当\(t = 0\),我们求\(\sqrt{A(0)}\),这个可以写cipolla
然后有
\(B(x) \equiv G(x) \pmod{x^{2^{t}}}\)
\(B(x) - G(x) \equiv 0 \pmod{x^{2^{t}}}\)
再平方
\(B(x)^{2} - 2B(x)G(x) + G(x)^2 \equiv 0 \pmod{x^{2^{t + 1}}}\)
然后把\(B(x)^2\)换成\(A(x)\)
\(A(x)- 2B(x)G(x) + G(x)^2 \equiv 0 \pmod{x^{2^{t + 1}}}\)
整理一下
\(B(x) \equiv \frac{A(x) + G(x)^2}{2G(x)} \pmod{x^{2^{t + 1}}}\)
多项式求ln
\(\ln F(x) = G(x)\)
两边分别求导
\(\frac{F'(x)}{F(x)} = G'(x)\)
然后再两边一起积分
\(\int \frac{F'(x)}{F(x)} = G(x)\)
所以多项式求ln只要求个导数,求个逆元,求个积分就好了
多项式求exp
根据牛顿迭代我们有。。
如果有个函数
\(B(A_t(x)) \equiv 0 \pmod{x^{2^{t}}}\)
\(A_{t + 1}(x) = A_{t}(x) - \frac{B(A_t(x))}{B'(A_t(x))}\)
注意下面求导的主元是\(A_t(x)\)而不是\(x\)
这个可以用泰勒展开展开证一下。。
\(B(A_{t + 1}(x)) \equiv 0 \pmod{x^{2^{t + 1}}}\)
\(0 = B(A_{t + 1}(x)) = B(A_t(x)) + \frac{B'(A_t(x))(A_{t + 1}(x) - A_{t}(x))}{1!} + \frac{B''(A_t(x))(A_{t + 1}(x) - A_t(x))^2}{2!}\cdots\)
自第三项及以后,最低项就是\(x^{2^{t + 1}}\)
所以可以化简成
\(0 = B(A_t(x)) + B'(A_{t}(x))(A_{t + 1}(x) - A_t(x))\)
然后就可以得到
\(A_{t + 1}(x) = A_t(x) - \frac{B(A_t(x))}{B'(A_{t}(x))}\)
然后……
\(e^{F(x)} \equiv G_{t}(x) \pmod{x^{2^{t}}}\)
然后同时取\(\ln\)
\(F(x) - \ln G_t(x) \equiv 0 \pmod {x^{2^{t}}}\)
然后就是刚刚那个式子咯。。
\(G_{t + 1}(x) \equiv G_{t}(x) - \frac{F(x) - \ln(G(x))}{-\frac{1}{G(x)}}\pmod{x^{2^{t + 1}}}\)
还是刚刚那句话。。主元是\(G_t(x)\)不是\(x\),所以\(F(x)\)相当于一个常数项。。
\(G_{t + 1}(x) \equiv G_{t}(x) + G_t(x)(F(x) - \ln(G(x))) \pmod {x^{2^{t + 1}}}\)
然后就可以做了
多项式快速幂
\(A^{k}(x) = e^{k \ln A(x)}\)
写的话有个小细节。。就是注意运算的时候指数取模不是对N取模,是对\(2^t\)取模。。
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define MAXN 20000005
#define eps 1e-10
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 998244353,MAXL = (1 << 21);
int W[MAXL + 5],N,K,Inv[MAXL + 5];
int inc(int a,int b) {
return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
return 1LL * a * b % MOD;
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = mul(res,t);
t = mul(t,t);
c >>= 1;
}
return res;
}
namespace Cipolla {
int a,s;
struct Complex {
int r,i;
Complex(int _x = 0,int _y = 0) {r = _x;i = _y;}
friend Complex operator + (const Complex &a,const Complex &b) {
return Complex(inc(a.r,b.r),inc(a.i,b.i));
}
friend Complex operator - (const Complex &a,const Complex &b) {
return Complex(inc(a.r,MOD - b.r),inc(a.i,MOD - b.i));
}
friend Complex operator * (const Complex &a,const Complex &b) {
return Complex(inc(mul(a.r,b.r),mul(mul(a.i,b.i),s)),inc(mul(a.r,b.i),mul(a.i,b.r)));
}
};
u32 Rand() {
static u32 x = 20020421;
return x += x << 2 | 1;
}
Complex Fpow(Complex x,int c) {
Complex res(1,0),t = x;
while(c) {
if(c & 1) res = res * t;
t = t * t;
c >>= 1;
}
return res;
}
int Sqrt(int N) {
while(1) {
a = Rand() % MOD;
s = inc(mul(a,a),MOD - N);
if(fpow(s,(MOD - 1) / 2) == MOD - 1) break;
}
Complex res(a,1);
res = Fpow(res,(MOD + 1) / 2);
if(res.r > MOD - res.r) res = MOD - res.r;
return res.r;
}
};
struct Poly {
vector<int> v;
Poly() {v.clear();}
Poly(int a) {v.clear();v.pb(a);}
Poly limit(int len = N) {
if(!v.size()) v.pb(0);
if(v.size() > len) v.resize(len);
int t = v.size() - 1;
while(t && v[t] == 0) {v.pop_back();--t;}
return *this;
}
friend Poly operator + (Poly a,Poly b) {
int h = max(a.v.size(),b.v.size());
a.v.resize(h);b.v.resize(h);
Poly c;
for(int i = 0 ; i < h ; ++i) {
c.v.pb(inc(a.v[i],b.v[i]));
}
return c;
}
friend Poly operator - (Poly a,Poly b) {
int h = max(a.v.size(),b.v.size());
a.v.resize(h),b.v.resize(h);
Poly c;
for(int i = 0 ; i < h ; ++i) {
c.v.pb(inc(a.v[i],MOD - b.v[i]));
}
return c;
}
friend void NTT(Poly &a,int L,int on) {
a.v.resize(L);
for(int i = 1 ,j = L >> 1 ; i < L - 1 ; ++i) {
if(i < j) swap(a.v[i],a.v[j]);
int k = L >> 1;
while(j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
for(int h = 2 ; h <= L ; h <<= 1) {
int wn = W[(MAXL + MAXL / h * on) % MAXL];
for(int k = 0 ; k < L ; k += h) {
int w = 1;
for(int j = k ; j < k + h / 2 ; ++j) {
int u = a.v[j],t = mul(a.v[j + h / 2],w);
a.v[j] = inc(u,t);
a.v[j + h / 2] = inc(u,MOD - t);
w = mul(w,wn);
}
}
}
if(on == -1) {
int InvL = fpow(L,MOD - 2);
for(int i = 0 ; i < L ; ++i) a.v[i] = mul(a.v[i],InvL);
}
}
friend Poly operator * (const int &a,const Poly &b) {
Poly c;int l = b.v.size();
for(int i = 0 ; i < l ; ++i) c.v.pb(mul(a,b.v[i]));
return c;
}
friend Poly operator * (Poly a,Poly b) {
Poly c;
int t = a.v.size() + b.v.size(),l = 1;
while(l <= t) l <<= 1;
a.v.resize(l);b.v.resize(l);
NTT(a,l,1);NTT(b,l,1);
c.v.resize(l);
for(int i = 0 ; i < l ; ++i) c.v[i] = mul(a.v[i],b.v[i]);
NTT(c,l,-1);
return c.limit();
}
friend Poly inverse(Poly a,int t) {
if(t == 1) return Poly(fpow(a.v[0],MOD - 2));
a.limit(t);
Poly b = inverse(a,t >> 1);
int l = b.v.size() + b.v.size() + a.v.size();
int len = 1;
while(len <= l) len <<= 1;
NTT(b,len,1);NTT(a,len,1);
Poly c;c.v.resize(len);
for(int i = 0 ; i < len ; ++i) c.v[i] = inc(mul(2,b.v[i]),MOD - mul(mul(b.v[i],b.v[i]),a.v[i]));
NTT(c,len,-1);
return c.limit(t);
}
friend Poly Inverse(const Poly &a,int t = N) {
int l = 1;
while(l < t) l <<= 1;
return inverse(a,l).limit(t);
}
friend Poly sub_sqrt(Poly a,int t) {
if(t == 1) return Poly(Cipolla::Sqrt(a.v[0]));
a.limit(t);
Poly b = sub_sqrt(a,t >> 1);
Poly inv = 2 * b;inv.v.resize(t);inv = Inverse(inv,t);
int l = inv.v.size() + max(b.v.size() + b.v.size(),a.v.size()),len = 1;
while(len <= l) len <<= 1;
NTT(inv,len,1);NTT(b,len,1);NTT(a,len,1);
Poly c;c.v.resize(len);
for(int i = 0 ; i < len ; ++i) {
c.v[i] = mul(inc(a.v[i],mul(b.v[i],b.v[i])),inv.v[i]);
}
NTT(c,len,-1);
return c.limit(t);
}
friend Poly Sqrt(const Poly &a,int t = N) {
int l = 1;
while(l < t) l <<= 1;
return sub_sqrt(a,l).limit(t);
}
friend Poly Derivative(const Poly &a) {
Poly c;c.v.resize(a.v.size() - 1);
for(int i = 0 ; i < a.v.size() - 1 ; ++i) {
c.v[i] = mul(a.v[i + 1],i + 1);
}
return c;
}
friend Poly Integral(const Poly &a) {
Poly c;c.v.resize(a.v.size() + 1);
for(int i = 1 ; i <= a.v.size() ; ++i) {
c.v[i] = mul(a.v[i - 1],Inv[i]);
}
return c;
}
friend Poly ln(Poly a,int t = N) {
Poly c = Inverse(a,t),d = Derivative(a);
int l = c.v.size() + d.v.size(),len = 1;
while(len <= l) len <<= 1;
NTT(c,len,1);NTT(d,len,1);
Poly res;res.v.resize(len);
for(int i = 0 ; i < len ; ++i) res.v[i] = mul(c.v[i],d.v[i]);
NTT(res,len,-1);
return Integral(res).limit(t);
}
friend Poly sub_exp(Poly a,int t) {
if(t == 1) {return Poly(1);}
a.limit(t);
Poly b = sub_exp(a,t >> 1);
Poly lnb = ln(b,t);
int l = b.v.size() + max(lnb.v.size(),a.v.size()),len = 1;
while(len <= l) len <<= 1;
NTT(lnb,len,1);NTT(b,len,1);NTT(a,len,1);
Poly c;c.v.resize(len);
for(int i = 0 ; i < len ; ++i) {
c.v[i] = inc(b.v[i],mul(b.v[i],inc(a.v[i],MOD - lnb.v[i])));
}
NTT(c,len,-1);
return c.limit(t);
}
friend Poly Exp(Poly a) {
int l = 1;
while(l < a.v.size()) l <<= 1;
return sub_exp(a,l).limit();
}
friend Poly operator ^ (const Poly &a,const int &k) {
return Exp(k * ln(a)).limit();
}
friend void Print(const Poly &a) {
for(int i = 0 ; i < a.v.size() ; ++i) {
out(a.v[i]);space;
}
enter;
}
}F,G;
void Solve() {
read(N);read(K);
int a;
for(int i = 0 ; i <= N ; ++i) {
read(a);
F.v.pb(a);
}
Inv[1] = 1;W[0] = 1;W[1] = fpow(3,(MOD - 1) / MAXL);
for(int i = 2 ; i < MAXL ; ++i) {
W[i] = mul(W[i - 1],W[1]);
Inv[i] = mul(Inv[MOD % i],MOD - MOD / i);
}
int tip = N;
N++;
G = Derivative((Poly(1) + ln(Poly(2) + F - Poly(F.v[0]) - Exp(Integral(Inverse(Sqrt(F))))))^K);
G.v.resize(tip);
Print(G);
enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}
【LOJ】#150. 挑战多项式的更多相关文章
- Solution -「LOJ #150」挑战多项式 ||「模板」多项式全家桶
\(\mathcal{Description}\) Link. 给定 \(n\) 次多项式 \(F(x)\),在模 \(998244353\) 意义下求 \[G(x)\equiv\left\{ ...
- [loj150]挑战多项式
以NTT为运算基础,即默认支持在$o(n\log n)$的时间内多项式乘法 二次剩余:称$n$为模$p$意义下的二次剩余,当且仅当存在$x$使得$x^{2}\equiv n(mod\ p)$ 当$p$ ...
- 数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群)
数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群) 因为不会做目录所以请善用ctrl+F 本来想的是笔记之类的,写着写着就变成了资源整理 一些有的 ...
- Tumblr:150亿月浏览量背后的架构挑战
Tumblr:150亿月浏览量背后的架构挑战 2013/04/08 · IT技术, 开发 · 9.9K 阅读 · HBase, Tumblr, 架构 英文原文:High Scalability,编译: ...
- [LOJ#525]「LibreOJ β Round #4」多项式
[LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...
- [JZOJ6088] [BZOJ5376] [loj #2463]【2018集训队互测Day 1】完美的旅行【线性递推】【多项式】【FWT】
Description Solution 我们考虑将问题一步步拆解 第一步求出\(F_{S,i}\)表示一次旅行按位与的值为S,走了i步的方案数. 第二步答案是\(F_{S,i}\)的二维重复卷积,记 ...
- loj #108. 多项式乘法
#108. 多项式乘法 题目描述 这是一道模板题. 输入两个多项式,输出这两个多项式的乘积. 输入格式 第一行两个整数 n nn 和 m mm,分别表示两个多项式的次数. 第二行 n+1 n + ...
- loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)
题面 传送门 题解 肝了一个下午--我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)--结果看它推倒简直一脸懵逼-- 做这题首先你得知道拉格朗日反演是个什么东西->这里 请坐稳,接下来 ...
- loj 6051 「雅礼集训 2017 Day11」PATH - 多项式 - 钩子公式
题目传送门 传送门 设 $m = \sum_{i = 1}^{n} a_i$. 总方案数显然等于 $\frac{m!}{\prod_{i = 1}^{n} a_i!}$. 考虑这样一个网格图,第 $i ...
随机推荐
- (cx_Oracle.DatabaseError) DPI-1047: 64-bit Oracle Client library cannot be loaded: "libclntsh.so: cannot open shared object file: No such file or directory"
打开https://oracle.github.io/odpi/doc/installation.html 官方相关如下 Oracle Instant Client RPM¶ To run ODPI- ...
- C#检测鼠标移动消息
当C#窗口上有其它控件时,窗口本身检测不到消息.1.使用WndProc.MouseMove不行,比如 protected override void WndProc(ref Message m) { ...
- 工控安全入门之Modbus(转载)
工控安全这个领域比较封闭,公开的资料很少.我在读<Hacking Exposed Industrial Control Systems>,一本16年的书,选了的部分章节进行翻译,以其抛砖引 ...
- VC++中LogFont设置字体(转)
LOGFONT是Windows内部字体的逻辑结构,主要用于设置字体格式,其定义如下:typedef struct tagLOGFONTA{LONG lfHeight;LONG lfWidth;LONG ...
- HDU2255 奔小康赚大钱 【KM算法】
题意: 每个人对不同房有不同出价,就是就是怎样匹配卖房让收入达到最大. 思路: 建立二分图,一边为N家老百姓,还有一边为N间房子.对老百姓和房子之间估价建立一条有带权边.问题就转变为了再二分图中找出一 ...
- node版本管理工具nvm安装以及使用
curl命令安装 curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.1/install.sh | bash 或者 使用wg ...
- B. Light It Up
题目链接:http://codeforces.com/problemset/problem/1000/B 代码: #include<iostream> #include<cstrin ...
- JavaScript学习 - 基础(六) - DOM基础操作
DOM: DOM定义了访问HTML 和XML 文档的标准:1.核心DOM 针对结构化文档的标准模型2.XMK DOM 针对XML文档的标准模型3.HTML DOM 针对HTML文档的标准模型 DOM节 ...
- CNN可解释
1 http://bindog.github.io/blog/2018/02/10/model-explanation/ http://www.sohu.com/a/216216094_473283 ...
- 2018-2019-2 网络对抗技术 20165320 Exp4 恶意代码分析
2018-2019-2 网络对抗技术 20165320 Exp4 恶意代码分析 一.实践目标 监控你自己系统的运行状态,看有没有可疑的程序在运行 分析一个恶意软件,就分析Exp2或Exp3中生成后门软 ...