题意

给定 $n$ , 求下式的值:

$$ f(n)= \sum_{i=0}^n\sum_{j=0}^i\begin{Bmatrix}i\\ j\end{Bmatrix}\times 2^j\times j!$$

题解

这题比较神仙...

那么我们可以思考如何来求一个比较简单的转移式.

首先我们发现, $f(n)$ 表达式中的第一重和式包含了 $f(n-1)$, 那么我们对 $f$ 的值做差分, 于是我们有 $f(n)-f(n-1)=\sum\limits_{i=0}^n\begin{Bmatrix}i\\ j\end{Bmatrix}\times 2^j\times j!$ .设 $g(n)=f(n)-f(n-1)$.

而我们知道第二类斯特林数的组合意义是在 $i$ 个物品中选 $j$ 个子集的方案数. 那么后面的 $j!$ 的组合意义相当于让划分的子集带标号, $2^j$ 的组合意义相当于每个子集贡献两种状态.

知道了表达式的组合意义, 我们可以尝试用朴素DP来解它. 我们枚举一下最后一个子集中的元素个数为 $i$ (因为子集带标号, 我们相当于枚举最后一个), 那么我们就有递推式:

$$g(n)=[n=0]+\sum_{i=1}^n {n\choose i} g(n-i)\times 2$$

最后乘 $2$ 是因为每个集合会贡献两种状态, $[n=0]$ 是边界条件.

观察这个式子, 发现是二项卷积的形式, 我们果断上EGF来解决. 设 $G(x)$ 是 $g(n)$ 的EGF, $H(x)$ 是数列 $\langle 0,2,2,2,\dots \rangle$ 的EGF, 那么我们有:

$$ G(x)=G(x)H(x)+1 $$

注意到 $H(x)$ 代表的数列的第 $0$ 项是 $0$, 因为 $g(n)$ 的递推式中求和下指标是 $1$.

那么我们移项之后就可以开心地得到:

$$ G(x)=\frac 1 {1-H(x)} $$

NTT爆算一发就可以了

代码实现

记得EGF要除以阶乘...出答案的时候还得乘回来...

 #include <bits/stdc++.h>

 const int G=;
const int DFT=;
const int IDFT=-;
const int MAXN=;
const int MOD=;
const int INV2=(MOD+)>>;
const int PHI=MOD-; typedef std::vector<int> Poly; Poly Sqrt(Poly);
void Read(Poly&);
Poly Inverse(Poly);
Poly Ln(const Poly&);
Poly Exp(const Poly&);
void Print(const Poly&);
void NTT(Poly&,int,int);
Poly Pow(const Poly&,int);
Poly Integral(const Poly&);
Poly Derivative(const Poly&);
Poly operator*(Poly,Poly);
Poly operator/(Poly,Poly);
Poly operator%(Poly,Poly);
Poly operator+(const Poly&,const Poly&);
Poly operator-(const Poly&,const Poly&); int rev[MAXN]; int NTTPre(int);
int Pow(int,int,int); int main(){
int n;
scanf("%d",&n);
Poly h(n+),one(,);
h[]=;
for(int i=;i<=n;i++)
h[i]=1ll*h[i-]*Pow(i,MOD-,MOD)%MOD;
Poly g(Inverse(one-h));
int ans=;
int fact=;
for(int i=;i<=n;i++){
(ans+=1ll*g[i]*fact%MOD)%=MOD;
fact=1ll*fact*(i+)%MOD;
}
printf("%d\n",ans);
return ;
} void Read(Poly& a){
for(auto& i:a)
scanf("%d",&i);
} void Print(const Poly& a){
for(auto i:a)
printf("%d ",i);
puts("");
} Poly Pow(const Poly& a,int k){
Poly log=Ln(a);
for(auto& i:log)
i=1ll*i*k%MOD;
return Exp(log);
} Poly Sqrt(Poly a){
int len=a.size();
if(len==)
return Poly(,int(sqrt(a[])));
else{
Poly b=a;
b.resize((len+)>>);
b=Sqrt(b);
b.resize(len);
Poly inv=Inverse(b);
int bln=NTTPre(inv.size()+a.size());
NTT(a,bln,DFT);
NTT(inv,bln,DFT);
for(int i=;i<bln;i++)
a[i]=1ll*a[i]*INV2%MOD*inv[i]%MOD;
NTT(a,bln,IDFT);
for(int i=;i<len;i++)
b[i]=(1ll*b[i]*INV2%MOD+a[i])%MOD;
return b;
}
} Poly Exp(const Poly& a){
size_t len=;
Poly ans(,),one(,);
while(len<(a.size()<<)){
len<<=;
Poly b=a;
b.resize(len);
ans=ans*(one-Ln(ans)+b);
ans.resize(len);
}
ans.resize(a.size());
return ans;
} Poly Ln(const Poly& a){
Poly ans=Integral(Derivative(a)*Inverse(a));
ans.resize(a.size());
return ans;
} Poly Integral(const Poly& a){
int len=a.size();
Poly ans(len+);
for(int i=;i<len;i++)
ans[i]=1ll*a[i-]*Pow(i,MOD-,MOD)%MOD;
return ans;
} Poly Derivative(const Poly& a){
int len=a.size();
Poly ans(len-);
for(int i=;i<len;i++)
ans[i-]=1ll*a[i]*i%MOD;
return ans;
} Poly operator/(Poly a,Poly b){
int n=a.size()-,m=b.size()-;
Poly ans();
if(n>=m){
std::reverse(a.begin(),a.end());
std::reverse(b.begin(),b.end());
b.resize(n-m+);
ans=Inverse(b)*a;
ans.resize(n-m+);
std::reverse(ans.begin(),ans.end());
}
return ans;
} Poly operator%(Poly a,Poly b){
int n=a.size()-,m=b.size()-;
Poly ans;
if(n<m)
ans=a;
else
ans=a-(a/b)*b;
ans.resize(m);
return ans;
} Poly operator*(Poly a,Poly b){
int len=a.size()+b.size()-;
int bln=NTTPre(len);
NTT(a,bln,DFT);
NTT(b,bln,DFT);
for(int i=;i<bln;i++)
a[i]=1ll*a[i]*b[i]%MOD;
NTT(a,bln,IDFT);
a.resize(len);
return a;
} Poly operator+(const Poly& a,const Poly& b){
Poly ans(std::max(a.size(),b.size()));
std::copy(a.begin(),a.end(),ans.begin());
for(size_t i=;i<b.size();i++)
ans[i]=(ans[i]+b[i])%MOD;
return ans;
} Poly operator-(const Poly& a,const Poly& b){
Poly ans(std::max(a.size(),b.size()));
std::copy(a.begin(),a.end(),ans.begin());
for(size_t i=;i<b.size();i++)
ans[i]=(ans[i]+MOD-b[i])%MOD;
return ans;
} Poly Inverse(Poly a){
int len=a.size();
if(len==)
return Poly(,Pow(a[],MOD-,MOD));
else{
Poly b(a);
b.resize((len+)>>);
b=Inverse(b);
int bln=NTTPre(b.size()*+a.size());
NTT(a,bln,DFT);
NTT(b,bln,DFT);
for(int i=;i<bln;i++)
b[i]=(2ll*b[i]%MOD-1ll*b[i]*b[i]%MOD*a[i]%MOD+MOD)%MOD;
NTT(b,bln,IDFT);
b.resize(len);
return b;
}
} void NTT(Poly& a,int len,int opt){
a.resize(len);
for(int i=;i<len;i++)
if(rev[i]>i)
std::swap(a[i],a[rev[i]]);
for(int i=;i<len;i<<=){
int step=i<<;
int wn=Pow(G,(PHI+opt*PHI/step)%PHI,MOD);
for(int j=;j<len;j+=step){
int w=;
for(int k=;k<i;k++,w=1ll*w*wn%MOD){
int x=a[j+k];
int y=1ll*a[j+k+i]*w%MOD;
a[j+k]=(x+y)%MOD;
a[j+k+i]=(x-y+MOD)%MOD;
}
}
}
if(opt==IDFT){
int inv=Pow(len,MOD-,MOD);
for(int i=;i<len;i++)
a[i]=1ll*a[i]*inv%MOD;
}
} int NTTPre(int n){
int bln=,bct=;
while(bln<n){
bln<<=;
++bct;
}
for(int i=;i<bln;i++)
rev[i]=(rev[i>>]>>)|((i&)<<(bct-));
return bln;
} inline int Pow(int a,int n,int p){
int ans=;
while(n>){
if(n&)
ans=1ll*a*ans%p;
a=1ll*a*a%p;
n>>=;
}
return ans;
}

BZOJ 4555

[BZOJ 4555][Tjoi2016&Heoi2016]求和的更多相关文章

  1. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...

  2. BZOJ 4555: [Tjoi2016&Heoi2016]求和 [FFT 组合计数 容斥原理]

    4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...

  3. bzoj 4555 [Tjoi2016&Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化

    [Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 679  Solved: 534[Submit][S ...

  4. BZOJ 4555: [Tjoi2016&Heoi2016]求和 (NTT + 第二类斯特林数)

    题意 给你一个数 \(n\) 求这样一个函数的值 : \[\displaystyle f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i} \begin{Bmatrix} i \\ j ...

  5. bzoj 4555 [Tjoi2016&Heoi2016] 求和 —— 第二类斯特林数+NTT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4555 关于第二类斯特林数:https://www.cnblogs.com/Wuweizhen ...

  6. BZOJ 4555 [Tjoi2016&Heoi2016]求和 (多项式求逆)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4555 题目大意: 给定 \(S(n,m)\) 表示第二类斯特林数,定义函数 \(f(n ...

  7. bzoj 4555 [Tjoi2016&Heoi2016]求和——NTT+第二类斯特林数

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4555 第二类斯特林数展开式: \( S(i,j) = \frac{1}{j!} \sum\l ...

  8. bzoj 4555: [Tjoi2016&Heoi2016]求和【NTT】

    暴力推式子推诚卷积形式,但是看好多blog说多项式求逆不知道是啥.. \[ \sum_{i=0}^{n}\sum_{j=0}^{n}S(i,j)*2^j*j! \] \[ S(i,j)=\frac{1 ...

  9. BZOJ 4555:[TJOI2016&HEOI2016]求和(第二类斯特林数+NTT)

    题目链接 \(Description\) 求 \[\sum_{i=0}^n\sum_{j=0}^iS(i,j)2^jj!\]对998244353取模后的结果. \(n<=10^5\) \(Sol ...

随机推荐

  1. 实现一个简单的"jQuery"

    本次博客记录一个简单的"jQuey"的实现方式,来加深对jQuery的理解: 代码: <!DOCTYPE html> <html> <head> ...

  2. 撩课-Java每天10道面试题第4天

    撩课Java+系统架构 视频 点击开始学习 31.静态变量和实例变量的区别? 静态变量也叫类变量, 这种变量前加了static修饰符. 可以直接用类名调用, 也可以用对象调用, 而且所有对象的同一个类 ...

  3. java:模拟栈操作

    import java.util.ArrayList; public class MyStack { private ArrayList<Object> arrayList; public ...

  4. js中的同步与异步的问题

    前言 近来,总是忙于拿js写一些案例,因为是小白,并没有什么丰富的经验,对各个知识点把握也不是很全面,写起来真的是...一言难尽,太痛苦了= =.尤其是在写一些轮播的时候,里面需要用到定时器,而一旦用 ...

  5. DOM基础操作实战代码

    对于已经讲解给大家的DOM实战,我今天给大家几个实战代码,可以让大家加深对此的理解! 1.用DOM动态生成这样一个结构: <div class=”example”> <p class ...

  6. CF954I Yet Another String Matching Problem

    传送门 每次操作可以把两个字符串中所有同一种字符变成另外一种 定义两个长度相等的字符串之间的距离为:使两个字符串相等所需要操作的次数的最小值 求 \(s\) 中每一个长度为 \(|t|\) 的连续子串 ...

  7. Bzoj4044 Virus synthesis

    题意 你要用 \(ATGC\) 四个字母用两种操作拼出给定的串: 将其中一个字符放在已有串开头或者结尾 将已有串复制,然后 \(reverse\) ,再接在已有串的头部或者尾部 一开始已有串为空.求最 ...

  8. Android 弹出框Dialog并缩放图片

    java代码 Activity: // 调用dialog,参数:1:自身的activity,2:Bitmap bm读取好的图片 MyDialog dialog = new MyDialog(MyAct ...

  9. Word 最后一页无法删除-解决办法

    Word 最后一页无法删除-解决办法 制服 word 最后一页无法删除 今天在做一个简历的时候,编辑 word 文档的时候,最后一页空白页怎么也删不掉,百度了很多方法之后,只有一个可行,记录一下. 1 ...

  10. 如何提高 Java 中锁的性能

    锁不是问题的根源,锁之间的竞争才是 通常在多线程的代码中遇到性能方面的问题时,一般都会抱怨是锁的问题.毕竟锁会降低程序的运行速度和其较低的扩展性是众所周知的.因此,如果带着这种“常识”开始优化代码,其 ...