Live2D

题解 下降幂多项式乘法

题目传送门

题目大意

给出两个次数分别为n,m的下降幂多项式,表示为:

F(x)=i=0naixi_,G(x)=i=0nbixi_

求出一个下降幂多项式H(x)使得对于x,H(x)=F(x)G(x)

n,m105

思路

有一个思路特别naive但是码起来会死人的方法,就是两个下降幂多项式转换成普通多项式,然后乘起来再转换成下降幂多项式。时间复杂度Θ(nlog2n),常数估计也贼大,估计是通过不了这道题的。

以下内容借鉴了command-block的题解。

我们发现我们其实用与多项式乘法相同的做法,我们把下降幂多项式转换成点值表示法然后乘起来再转换成下降幂多项式。问题就是我们如何把一个下降幂多项式转换成点值表示法。

我们假设要转换的下降幂多项式为F,我们假设点值的EGFF1

我们发现如果F(x)=xn_,那我们可以得到F1(x)为:

i=0in_xii!=i=0xi(ni)!=xni=0xii!=xnex

而我们根据定义可以得到:

F1(x)=i=0F(i)xii!

又因为F(x)=i=0F[i]xi_,所以我们可以得到:

F1(x)=i=0xii!j=0F[j]ij_

=j=0F[j]i=0ij_xii!

=j=0F[j]xjex

=exj=0F[j]xj

于是,我们就可以直接普通多项式乘法Θ(nlogn)求出一个下降幂多项式的点值的EGF,求出来之后直接乘起来。那要从点值EGF转换成下降幂多项式很显然直接乘上ex,这个东西用泰勒展开(显然)就是:

i=0(1)ixii!

Code

Copy
#pragma GCC optimize("Ofast") #pragma GCC optimize("inline", "no-stack-protector", "unroll-loops") #pragma GCC diagnostic error "-fwhole-program" #pragma GCC diagnostic error "-fcse-skip-blocks" #pragma GCC diagnostic error "-funsafe-loop-optimizations" #include <bits/stdc++.h> using namespace std; #define SZ(x) ((int)x.size()) #define Int register int #define mod 998244353 #define MAXN 1600005 int mul (int a,int b){return 1ll * a * b % mod;} int dec (int a,int b){return a >= b ? a - b : a + mod - b;} int add (int a,int b){return a + b >= mod ? a + b - mod : a + b;} int qkpow (int a,int k){ int res = 1;for (;k;k >>= 1,a = 1ll * a * a % mod) if (k & 1) res = 1ll * res * a % mod; return res; } int inv (int x){return qkpow (x,mod - 2);} typedef vector <int> poly; int up,w[MAXN],rev[MAXN]; void init_ntt (){ int lim = 1 << 19; for (Int i = 0;i < lim;++ i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << 18); int Wn = qkpow (3,(mod - 1) / lim);w[lim >> 1] = 1; for (Int i = lim / 2 + 1;i < lim;++ i) w[i] = mul (w[i - 1],Wn); for (Int i = lim / 2 - 1;i;-- i) w[i] = w[i << 1]; } void ntt (poly &a,int lim,int type){ #define G 3 #define Gi 332748118 static unsigned long long d[MAXN]; for (Int i = 0,z = 19 - __builtin_ctz(lim);i < lim;++ i) d[rev[i] >> z] = a[i]; for (Int i = 1;i < lim;i <<= 1) for (Int j = 0;j < lim;j += i << 1) for (Int k = 0;k < i;++ k){ int x = 1ll * d[i + j + k] * w[i + k] % mod; d[i + j + k] = d[j + k] + mod - x,d[j + k] += x; } for (Int i = 0;i < lim;++ i) a[i] = d[i] % mod; if (type == -1){ reverse (a.begin() + 1,a.begin() + lim); for (Int i = 0,Inv = inv (lim);i < lim;++ i) a[i] = mul (a[i],Inv); } #undef G #undef Gi } poly operator * (poly a,poly b){ int d = SZ (a) + SZ (b) - 1,lim = 1;while (lim < d) lim <<= 1; a.resize (lim),b.resize (lim); ntt (a,lim,1),ntt (b,lim,1); for (Int i = 0;i < lim;++ i) a[i] = mul (a[i],b[i]); ntt (a,lim,-1),a.resize (up + 1); return a; } template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;} template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);} template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} poly I,Iv,A,B; int n,m,fac[MAXN],ifac[MAXN]; signed main(){ init_ntt (),read (n,m);up = n + m;A.resize (n + 1),B.resize (m + 1); for (Int i = 0;i <= n;++ i) read (A[i]); for (Int i = 0;i <= m;++ i) read (B[i]); fac[0] = 1;for (Int i = 1;i <= up;++ i) fac[i] = mul (fac[i - 1],i); ifac[up] = inv (fac[up]);for (Int i = up;i;-- i) ifac[i - 1] = mul (ifac[i],i); I.resize (up + 1);for (Int i = 0;i <= up;++ i) I[i] = ifac[i]; A = A * I,B = B * I; for (Int i = 0;i <= up;++ i) A[i] = mul (mul (A[i],B[i]),fac[i]); Iv.resize (up + 1);for (Int i = 0;i <= up;++ i) Iv[i] = (i & 1 ? mod - ifac[i] : ifac[i]); A = A * Iv; for (Int i = 0;i <= up;++ i) write (A[i]),putchar (' '); putchar ('\n'); return 0; }

P.S.

本来没有卡过去,结果直接一波卡常就卡成rank 3了(至少在这个时候还是rank 3)。。。(雾

posted @   Dark_Romance  阅读(473)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示