传送门

Sol

(怎么老是有人喜欢出新的多项式毒瘤板子,懒得整到一起了)

核心就是把 幂用下降幂来代替。

使用斯特林数展开幂为下降幂:

\[x^n=\sum_{i=0}^n{x\choose i}i!S(n,i)=\sum_{i=0}^nS(n,i)x^{\underline i}
\]

那么要求的多项式:

\[\sum_{i=0}^{n-1}a_ix^i=\sum_{i=0}^{n-1}a_i\sum_{j=0}^jS(i,j)x^{\underline j}
\]

交换求和顺序:

\[\sum_{j=0}^{n-1}x^{\underline j}\sum_{i=j}^{n-1} a_iS(i,j)
\]

那么求出后面那个东西就行了。由于当 \(i<j\)时 \(S(i,j)=0\),所以 \(i\) 可以从 \(0\) 开始枚举。这个就是一个要求一列的斯特林数的模型。

把斯特林数拆开:

\[\sum_{i=0}^{n-1}\frac{a_i}{j!}\sum_{k=0}^j (-1)^{j-k}{j\choose k}k^i
\]

组合数拆开形成卷积:

\[\sum_{k=0}^j\frac{(-1)^{j-k}}{(j-k)!}*\sum_{i=0}^{n-1}\frac{a_ik^i}{k!}
\]

令 \(f_k=\frac{(-1)^k}{k!},g_k=\sum_{i=0}^{n-1}\frac{a_ik^i}{k!}\) ,那么对 \(F(x)\)与\(G(x)\)做卷积即可。

求 \(G(x)\) 需要多项式多点求值。

code:

#include<bits/stdc++.h>
#define Set(a,b) memset(a,b,sizeof(a))
#define Clear(a,_begin_,_end_) for(int i=_begin_;i<_end_;++i) a[i]=0
#define Input_Array(a,_begin_,_end_) for(int i=_begin_;i<_end_;++i) init(a[i])
#define __ NULL
using namespace std;
const int N=1e5+10,MAXN=N<<2,MAXM=5e6;
typedef vector<int> Poly;
template <typename T> inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}typedef double db;
typedef long long ll;
int Inv[MAXN],rader[MAXN];
const int mod=998244353,phi=998244352,SIZE=sizeof(rader),inv2=499122177;
template<typename T>inline void Inc(T&x,int y){x+=y;if(x>=mod) x-=mod;return;}
template<typename T>inline void Dec(T&x,int y){x-=y;if(x < 0) x+=mod;return;}
template<typename T>inline int fpow(int x,T k){int ret=1;for(;k;k>>=1,x=(ll)x*x%mod) if(k&1) ret=(ll)ret*x%mod;return ret;}
inline int Sum(int x,int y){x+=y;if(x>=mod) return x-mod;return x;}
inline int Dif(int x,int y){x-=y;if(x < 0 ) return x+mod;return x;}
inline int Init(int n){int len=1,up=-1;while(len<=n) len<<=1,++up;for(int i=0;i<len;++i) rader[i]=(rader[i>>1]>>1)|((i&1)<<up);return len;}
inline void Calc_Inversion(){Inv[1]=1;for(int i=2;i<MAXN;++i) Inv[i]=(ll)(mod-mod/i)*Inv[mod%i]%mod;return;}
namespace NTT{
int wn[30],iwn[30];
inline void Calcw(){for(int i=0;i<30;++i) wn[i]=fpow(3,phi/(1<<i)),iwn[i]=fpow(wn[i],mod-2);}
inline void NTT(int*A,int n,int f){
for(int i=0;i<n;++i) if(rader[i]>i) swap(A[i],A[rader[i]]);
for(int i=1,h=1;i<n;++h,i<<=1){
int W=(~f)? wn[h]:iwn[h];
for(int j=0,p=i<<1;j<n;j+=p){
for(int w=1,k=0;k<i;++k,w=(ll)w*W%mod){
int X=A[j|k],Y=(ll)w*A[j|k|i]%mod;
A[j|k]=Sum(X,Y),A[j|k|i]=Dif(X,Y);
}
}
}if(!~f) for(int i=0;i<n;++i) A[i]=(ll)A[i]*Inv[n]%mod;
return;
}
inline void Mul(int*a,int*b,int*c,int n,int m) {
int L=n+m-1;int len=Init(L);static int A[MAXN],B[MAXN];
for(int i=0;i<n;++i) A[i]=a[i];for(int i=0;i<m;++i) B[i]=b[i];
Clear(A,n,len);Clear(B,m,len);NTT(A,len,1),NTT(B,len,1);
for(int i=0;i<len;++i) c[i]=(ll)A[i]*B[i]%mod;
NTT(c,len,-1);return;
}
inline void Poly_Inv(int*F,int*I,int n){
if(n==1) {memset(I,0,SIZE);I[0]=fpow(F[0],mod-2);return;}
Poly_Inv(F,I,(n+1)>>1);int L=n<<1,len=Init(L);
static int A[MAXN];for(int i=0;i<n;++i) A[i]=F[i];Clear(A,n,len);
NTT(I,len,1);NTT(A,len,1);
for(int i=0;i<len;++i) I[i]=Dif(Sum(I[i],I[i]),(ll)I[i]*I[i]%mod*A[i]%mod);
NTT(I,len,-1);Clear(I,n,len);return;
}
inline void Poly_Mod(int*A,int*B,int*Q,int*R,int n,int m){
if(n<m) {for(int i=0;i<=n;++i) R[i]=A[i];return;}
static int C[MAXN],D[MAXN],E[MAXN];
const int r=(n-m)<<1;int len=1;while(len<=r)len<<=1;
for(int i=0;i<=n-m;++i) D[i]=A[n-i];Clear(D,n-m+1,len);
for(int i=0;i<=m;++i) E[i]=B[m-i];Clear(E,m+1,len);
Poly_Inv(E,C,n-m+1);len=Init(r);NTT(C,len,1),NTT(D,len,1);
for(int i=0;i<len;++i) C[i]=(ll)C[i]*D[i]%mod;
NTT(C,len,-1);reverse(E,E+1+m),reverse(C,C+1+n-m);
if(Q) for(int i=0;i<=n-m;++i) Q[i]=C[i];
len=Init(n);Clear(C,n-m+1,len);Clear(E,m+1,len);
NTT(C,len,1),NTT(E,len,1);
for(int i=0;i<len;++i) C[i]=(ll)C[i]*E[i]%mod;
NTT(C,len,-1);for(int i=0;i<m;++i) R[i]=Dif(A[i],C[i]);
return;
}
#define ls (u<<1)
#define rs (u<<1|1)
int POOL[MAXM],cnt=0;
int *P[MAXN],*F[MAXN],*G[MAXN],X[N],*val;
inline int* Neospace(int len){int*ret=&POOL[cnt];cnt+=len;return ret;}
inline int Calc(int*F,int n,const int x){int X=1,ret=0;for(int i=0;i<n;++i) Inc(ret,(ll)F[i]*X%mod),X=(ll)X*x%mod;return ret;}
inline void Divide(int u,int l,int r){P[u]=NULL;//分治+NTT , 保留了中间的结果
if(l==r) {P[u]=Neospace(2);P[u][0]=mod-X[l];P[u][1]=1;return;}
static int L[MAXN],R[MAXN];int mid=(l+r)>>1;int LS=ls,RS=rs;
Divide(LS,l,mid);Divide(RS,mid+1,r);
int n=r-l+2,nl=mid-l+2,nr=r-mid+1;
for(int i=0;i<nl;++i) L[i]=P[LS][i];
for(int i=0;i<nr;++i) R[i]=P[RS][i];
Mul(L,R,L,nl,nr);P[u]=Neospace(n);
for(int i=0;i<n;++i) P[u][i]=L[i];
return;
}
inline void Poly_Evaluate(int u,int l,int r){// 多点求值
if(r-l+1<=500) {for(int i=l;i<=r;++i) val[i]=Calc(F[u],r-l+1,X[i]);return;}// 长度小的暴力计算
int mid=(l+r)>>1,LS=ls,RS=rs;
int n=r-l+1,nl=mid-l+1,nr=r-mid;
static int R[MAXN];
F[LS]=Neospace(nl),F[RS]=Neospace(nr);
Poly_Mod(F[u],P[LS],__,R,n-1,nl);
for(int i=0;i<nl;++i) F[LS][i]=R[i];
Poly_Mod(F[u],P[RS],__,R,n-1,nr);
for(int i=0;i<nr;++i) F[RS][i]=R[i];
Poly_Evaluate(LS,l,mid);
Poly_Evaluate(RS,mid+1,r);
return;
}
inline void Solve_Evaluation(int*A,int*_X,int*ans,int n,int m){
cnt=0;F[1]=Neospace(m);val=ans;
for(int i=1;i<=m;++i) X[i]=_X[i];Divide(1,1,m);
Poly_Mod(A,P[1],__,F[1],n-1,m);//注意最开始的多项式也要取一次模
Poly_Evaluate(1,1,m);return;
}
}
int fac[N],finv[N];
int main()
{
Calc_Inversion();NTT::Calcw();
int n;fac[0]=finv[0]=1;init(n);
for(int i=1;i<n;++i) fac[i]=(ll)fac[i-1]*i%mod,finv[i]=(ll)finv[i-1]*Inv[i]%mod;
static int F[MAXN],A[MAXN],X[MAXN];
for(int i=0;i<n;++i) init(A[i]),X[i+1]=i,F[i]=(i&1)? (mod-finv[i]):finv[i];
NTT::Solve_Evaluation(A,X,X,n,n);
for(int i=0;i<n;++i) X[i]=(ll)X[i+1]*finv[i]%mod;X[n]=0;
NTT::Mul(X,F,F,n,n);
for(int i=0;i<n;++i) printf("%d ",F[i]);putchar('\n');
return 0;
}

【LuoguP5383】[模板]普通多项式转下降幂多项式的更多相关文章

  1. UOJ269 清华集训2016 如何优雅地求和 下降幂多项式、NTT

    代码 神仙题? 看到连续的点值,那么一定是要利用到连续点值的性质,可以考虑下降幂多项式,即考虑多项式\(F(x) = \sum\limits_{i=0}^m a_ix^{\underline i}\) ...

  2. 洛谷 P6667 - [清华集训2016] 如何优雅地求和(下降幂多项式,多项式)

    题面传送门 wjz:<如何优雅地 AK NOI> 我:如何优雅地爆零 首先,按照这题总结出来的一个小套路,看到多项式与组合数结合的题,可以考虑将普通多项式转为下降幂多项式,因为下降幂和组合 ...

  3. FFT模板 生成函数 原根 多项式求逆 多项式开根

    FFT #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> ...

  4. CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)

    传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多 ...

  5. NTT+多项式求逆+多项式开方(BZOJ3625)

    定义多项式$h(x)$的每一项系数$h_i$,为i在c[1]~c[n]中的出现次数. 定义多项式$f(x)$的每一项系数$f_i$,为权值为i的方案数. 通过简单的分析我们可以发现:$f(x)=\fr ...

  6. 【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆

    题目大意 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots ,c_n\).如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合\(\{c_1,c_2,\ldots ,c_n\ ...

  7. 2019.01.01 bzoj3625:小朋友和二叉树(生成函数+多项式求逆+多项式开方)

    传送门 codeforces传送门codeforces传送门codeforces传送门 生成函数好题. 卡场差评至今未过 题意简述:nnn个点的二叉树,每个点的权值KaTeX parse error: ...

  8. 【BZOJ3625】【codeforces438E】小朋友和二叉树 生成函数+多项式求逆+多项式开根

    首先,我们构造一个函数$G(x)$,若存在$k∈C$,则$[x^k]G(x)=1$. 不妨设$F(x)$为最终答案的生成函数,则$[x^n]F(x)$即为权值为$n$的神犇二叉树个数. 不难推导出,$ ...

  9. [Codeforces438E][bzoj3625] 小朋友和二叉树 [多项式求逆+多项式开根]

    题面 传送门 思路 首先,我们把这个输入的点的生成函数搞出来: $C=\sum_{i=0}^{lim}s_ix^i$ 其中$lim$为集合里面出现过的最大的数,$s_i$表示大小为$i$的数是否出现过 ...

随机推荐

  1. 亚马逊s3存储: aws cli上传工具速度和各文件大小关系探究

    1,背景介绍 公司最近最近统一了存储环境,由ftp文件存储全量转换为ceph存储.有业务组表示以前往ftp文件批量上传30万个文件1.3GB只需要16分钟左右.切换为ceph存储需要1个多小时,也就是 ...

  2. C++学习笔记-继承

    类之间可以建立联系,这就使得类可以有某种关系 类之间的关系 has-A:包含关系,一个类使用另一个已经定义好的类的数据 uses-A:使用关系,友元或者对象参数传递 is-A:是的关系,这就是继承,具 ...

  3. C++学习 之 指针及动态内存分配(笔记)

    1. 指针 1.1 指针的含义: 简单来说,指针是存储内存地址的变量.当我们声明了一个指针变量后,使用该指针时系统会根据指针内的地址索引内存块,读取内存内的值.指针因为是用来存地址的,所以一般固定长度 ...

  4. 坦克大战--Java类型 ---- (1)音乐播放

    实现原理 我用接口java.applet.AudioClip实现音乐播放,那么我们需要了解这个接口的情况. 我们主要使用其中的三个方法: (1)void loop(); //循环播放(2)void p ...

  5. 面试题1-十进制数转化为十六进制数,不使用hex方法

    问题: 给定一个整数,写一个算法将它转换为16进制,对于负数,可以使用two’s complement方法 def tohex(num): """十进制数转十六进制数&q ...

  6. js判断设备,跳转app应用、android市场或者AppStore

    js移动设备判断方法大全 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" > ...

  7. idea 设置自动生成注释

    idea新建类注释规则 /** @ProjectName: ${PROJECT_NAME} @Package: ${PACKAGE_NAME} @ClassName: ${NAME} @Descrip ...

  8. WPF最小化窗体后激活函数显示不了窗体

    WPF最小化窗体后激活函数显示不了窗体 今天测试小哥给我提了一些问题,其中一个问题是这样的,点击web端的一个链接,是能启动本地的一个应用程序的,如果本地应用程序已启动(通过tcp进程间通信),那么应 ...

  9. C# 面向对象2 (类的语法)

    1.类 语法: [public] class 类名 { 字段; 属性; 方法; } **类名首字母必须大写 2.创建对象 创建这个类的对象过程称之为类的实例化,关键字:new this:表示当前这个类 ...

  10. 109、Secret的使用场景 (Swarm16)

    参考https://www.cnblogs.com/CloudMan6/p/8082429.html   我们可以用secret管理任何敏感数据.这些敏感数据是容器在运行时需要的.同时我们又不想把这些 ...