首页 > 其他分享 >多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)

多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)

时间:2023-02-21 10:08:01浏览次数:60  
标签:int 多项式 len ++ exp lim 求值 mod


预备知识:FFT/NTT

多项式的逆

给定一个多项式 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模,请求出一个多项式 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_02,满足 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_03
系数对 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_04 取模,多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_05

首先将多项式的长度拓展至多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_06的次幂,然后我们要求的是
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_07假设已经求出了
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_08又因为有
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_09两式相减有
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_10多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_11因为左边得到的多项式前多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_12项都是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_13,平方前多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_14项都是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_13,所以有
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_16多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_17两边同时乘以多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_19多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_20
我们就得到了递推式,时间复杂度如下多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_21

多项式开根

给定一个 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_22 次多项式 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模,求一个在 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_24 意义下的多项式 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_02,使得 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_26(多项式的系数在 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_27 的意义下进行运算,多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_05
同样假设求出了多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_29且有
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_30所以
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_11多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_16多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_17多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_34
所以多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_35
此处除法转化为乘上多项式的逆,就能递推了,时间复杂度也是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_36

多项式求自然对数

给出 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_22 次多项式 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模,求一个 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_24 下的多项式 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_02,满足 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_41.
多项式的系数在 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_27 的意义下进行运算,多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_05
多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_44所以多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_45,直接多项式求逆+多项式求导积分就行了
求逆复杂度多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_36,求导积分复杂度多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_47,总时间复杂度仍是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_36

多项式exp

多项式exp是用牛顿迭代做的,我也不会证明牛顿迭代,只会背公式.
本来牛顿迭代公式是这个样子的多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_49
对于多项式的牛顿迭代长这样多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_50

  • 其中多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_51表示已知多项式为多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_52,未知多项式为多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_53的多项式方程,就拿exp为例,原方程为多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_54两边取对数为多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_55那么多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_56.
  • 多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_57表示的是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_51多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_53取导.注意是对多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_53,不是对多项式里的多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_61.
    举个栗子,多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_62多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_52求导是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_64,但是对多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_61求导是多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_66(此处多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_取模_67是对多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_61求导)

那么我们就可以推推柿子多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_69然后就套用前面的模板迭代做了

多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式_70其实多项式开根也可以用这个方法推出来,有兴趣可以去试试看.

代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
namespace READ {
inline void read(int &num) {
char ch; int flg=1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
}
using namespace READ;
const int mod = 998244353, G = 3, inv2 = 499122177;
const int MAXN = 1<<18; // 注意MAXN要大于2*n
int rev[MAXN], Wn[MAXN+1][2], inv[MAXN+1];
inline void reset(int len) { for(int i = 0; i < len; ++i) rev[i] = (rev[i>>1]>>1)|((i&1)?(len>>1):0); }
inline int qmul(int a, int b) {
int res = 1;
while(b) {
if(b&1) res = 1ll * res * a % mod;
a = 1ll * a * a % mod; b>>=1;
}
return res;
}
inline int add(int x, int y) { return x+y>mod ? x+y-mod : x+y; }
namespace Poly {
int A[MAXN],B[MAXN],C[MAXN],D[MAXN],E[MAXN],F[MAXN],GG[MAXN],H[MAXN];//每个不同函数开不同的临时数组,否则可能重复使用
inline void clear(int *b, int n) { for(int i = 0; i < n; ++i) b[i] = 0; } //多清零
inline void NTT(int *arr, int n, int flg) {
int wn, w, A0, wA1, i, j, k;
for(i = 0; i < n; ++i) if(i < rev[i]) swap(arr[i], arr[rev[i]]);
for(i = 2; i <= n; i<<=1) {
wn = Wn[i][(~flg)?0:1];
for(j = 0, w = 1; j < n; j += i, w = 1)
for(k = j; k < j + i/2; ++k, w = 1ll * w * wn % mod) {
A0 = arr[k], wA1 = 1ll * w * arr[k + i/2] % mod;
arr[k] = add(A0, wA1);
arr[k + i/2] = add(A0, -wA1+mod);
}
}
if(!(~flg)) for(i = 0; i < n; ++i) arr[i] = 1ll * arr[i] * inv[n] % mod;
}

inline void INV(int *a, int *b, int n) {
clear(b, n<<1), b[0] = qmul(a[0], mod-2);
clear(A, n<<1), clear(B, n<<1);
int len, lim;
for(len = 2; len < (n<<1); len<<=1) {
lim = len<<1;
for(int i = 0; i < len; ++i) A[i] = a[i], B[i] = b[i];
reset(lim); NTT(A, lim, 1); NTT(B, lim, 1);
for(int i = 0; i < lim; ++i) b[i] = ((2ll - 1ll * A[i] * B[i] % mod) * B[i] % mod + mod) % mod;
NTT(b, lim, -1);
for(int i = len; i < lim; ++i) b[i] = 0;
}
for(int i = 0; i < len; ++i) A[i] = B[i] = 0;
for(int i = n; i < len; ++i) b[i] = 0;
}

inline void SQRT(int *a, int *b, int n) {
clear(b, n<<1); b[0] = int(sqrt(a[0])+0.5);
int len, lim, *A = GG, *B = H;
clear(A, n<<1), clear(B, n<<1);
for(len = 2; len < (n<<1); len<<=1) {
lim = len<<1;
for(int i = 0; i < len; ++i) A[i] = a[i];
INV(b, B, len);
reset(lim); NTT(A, lim, 1); NTT(B, lim, 1);
for(int i = 0; i < lim; ++i) A[i] = 1ll * A[i] * B[i] % mod;
NTT(A, lim, -1);
for(int i = 0; i < len; ++i) b[i] = 1ll * (b[i] + A[i]) % mod * inv2 % mod;
for(int i = len; i < lim; ++i) b[i] = 0;
}
for(int i = 0; i < len; ++i) A[i] = B[i] = 0;
for(int i = n; i < len; ++i) b[i] = 0;
}

inline void INT(int *a, int *b, int n) {
clear(b, n<<1);
for(int i = n-1; i; --i)
b[i] = 1ll * a[i-1] * qmul(i, mod-2) % mod;
b[0] = 0;
}

inline void DIF(int *a, int *b, int n) {
clear(b, n<<1);
for(int i = 1; i < n; ++i)
b[i-1] = 1ll * a[i] * i % mod;
b[n-1] = 0;
}

inline void LN(int *a, int *b, int n) {
int *A = E, *B = F, len = 1;
clear(A, n<<1), clear(B, n<<1);
INV(a, A, n); DIF(a, B, n);
while(len < (n<<1)) len<<=1;
reset(len); NTT(A, len, 1); NTT(B, len, 1);
for(int i = 0; i < len; ++i) A[i] = 1ll * A[i] * B[i] % mod;
NTT(A, len, -1); INT(A, b, n);
}

inline void EXP(int *a, int *b, int n) {
clear(b, n<<1), b[0] = 1;
int len, lim, *A = C, *B = D;
clear(A, n<<1), clear(B, n<<1);
for(len = 2; len < (n<<1); len<<=1) {
lim = len<<1;
LN(b, A, len);
for(int i = 0; i < len; ++i) A[i] = ((i==0)-A[i]+a[i]+mod) % mod, B[i] = b[i];
for(int i = len; i < lim; ++i) A[i] = B[i] = 0;
reset(lim); NTT(A, lim, 1); NTT(B, lim, 1);
for(int i = 0; i < lim; ++i) A[i] = 1ll * A[i] * B[i] % mod;
NTT(A, lim, -1);
for(int i = 0; i < len; ++i) b[i] = A[i];
}
for(int i = n; i < len; ++i) b[i] = 0;
}
}
using namespace Poly;
inline void Pre() { //预处理原根及逆元
for(int i = 1; i <= MAXN; i<<=1)
Wn[i][0] = qmul(G, (mod-1)/i),
Wn[i][1] = qmul(G, (mod-1)-(mod-1)/i),
inv[i] = qmul(i, mod-2);
}
int main () {
Pre();
}

多项式的各类计算(多项式的逆/开根/对数/exp/带余除法/多点求值)_多项式计算_71现在看,发现我以前sb了…不用开不同的数组来取地址,直接static定义就行了…

带余除法(待更…)

多项式多点求值(待更…)


标签:int,多项式,len,++,exp,lim,求值,mod
From: https://blog.51cto.com/u_15973510/6075813

相关文章

  • 【Azure 事件中心】Azure Event Hub客户端遇见 Expired Heartbeat 错误
    问题描述AzureEventHub在消费数端中,经常性遇见ExpiredHeartbeat错误(consumer-xxxxxxxxxxxxx-c84873c6c828e8df6c843861ad36affb fromgroupxxxxxxxxxxxxduetoex......
  • 【Azure 事件中心】Azure Event Hub客户端遇见 Expired Heartbeat 错误
    问题描述AzureEventHub在消费数端中,经常性遇见ExpiredHeartbeat错误(consumer-xxxxxxxxxxxxx-c84873c6c828e8df6c843861ad36affb fromgroupxxxxxxxxxxxxdueto......
  • volatile、mutable和explicit
    volatile用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化......
  • k8s中使用prometheus operator监控外部服务器部署的windows exporter
    k8s中使用prometheusoperator监控外部服务器部署的windowsexporter0、文档说明(1)PrometheusOperator是一个流行的k8s集群监控套件,项目地址:https://github.com/prom......
  • NuGet Package Explorer
    现代VisualStudio下的开发,大家一定用过,或者听说过nuget,不知道的可以去面壁了。代码写多了,经验越来越丰富,但人越来越懒,是啊,谁愿意重复造轮子?谁又愿意陷入版本管理的地狱?......
  • 【笔记】本原多项式之积仍为本原多项式
    定义:多项式\(f(x)=\sum_{i=0}^{n}a_ix^i\)是本原多项式(primitivepolynomial),如果\(\gcd(a_0,\cdots,a_n)=1\)。结论:本原多项式之积仍为本原多项式。证明:WLOG,设\(f(x......
  • 多项式杂题
    多项式特训。开始大生产运动。不得不说黑题通过数一下就上来了。由于大多数比较工业所以一律不放代码。歌被咕了,打算报复性整点活。整活其实不一定需要整活用的曲。目前......
  • DynamicExpression.Core
    DynamicExpression.Core.netlambda表达式合并 事情的起因是公司一个小伙子问了我个问题“海哥,来帮我看下这段代码怎么不行”Func<Report,bool>nameFilter=x=>x......
  • 【MySQL-Explain了解查询语句执行计划】
    零、本文纲要一、执行计划二、Explain输出格式三、Explain作用&局限性tips:Ctrl+F定位到所需内容阅读吧。一、执行计划执行计划是数据库根据SQL语句和相关表的统计信......
  • constexpr和define和const
    const:常量变量,本质是一个不可变的变量数据类型,不是常量define:预编译时直接进行文字替换,不具备计算能能力 constexpr:预编译时进行修饰,也可对常量表达式进行计算后修饰,本......