【题意】给定n,求Σi=0~nΣj=1~i s(i,j)*2^j*j!,n<=10^5。

【算法】生成函数+排列组合+多项式求逆

【题解】参考: [BZOJ4555][Tjoi2016&Heoi2016]求和-NTT-多项式求逆

$ans=\sum_{i=0}^{n}\sum_{j=0}^{i}s(i,j)*2^j*j!$

令$g(n)=\sum_{j=0}^{n}s(n,j)*2^j*j!$

则ans是Σg(i),只要计算出g(i)的生成函数就可以统计答案。

g(n)可以理解为将n个数划分成若干集合,每个集合有2个属性的排列数。基于此实际意义,通过枚举第一个集合来递推g(n)。

$g(n)=\sum_{i=1}^{n}2*C(n,i)*g(n-i)$

特别的,g(0)=1

两边乘n!(令人窒息的操作),得

$\frac{g(n)}{n!}=\sum_{i=1}^{n}\frac{2}{i!}*\frac{g(n-i)}{(n-i)!}$

这已经是卷积的形式了:

$F(n)=\sum_{i=1}^{n}\frac{2}{n!}*x^i$

$G(n)=\sum_{i=0}^{n}\frac{g(n)}{n!}*x^i$

注意此时F*G卷积后,G(0)的位置是0,所以

$G(n)=F(n)G(n)+1$

移项得,

$G(n)=\frac{1}{1-F(n)}$

最后,多项式求逆即可,复杂度O(n log n)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,MOD=;
void gcd(int a,int b,int &x,int &y){
if(!b){x=;y=;}else{gcd(b,a%b,y,x);y-=x*(a/b);}
}
int inv(int a){int x,y;gcd(a,MOD,x,y);return (x%MOD+MOD)%MOD;}
int power(int x,int k){
int ans=;
while(k){
if(k&)ans=1ll*ans*x%MOD;
x=1ll*x*x%MOD;
k>>=;
}
return ans;
}
namespace ntt{
int o[maxn],oi[maxn],f[maxn];
void init(int n){
int x=,p=power(,(MOD-)/n);
for(int k=;k<n;k++){
o[k]=x;oi[k]=inv(o[k]);
x=1ll*x*p%MOD;
}
}
void transform(int *a,int n,int *o){
int k=;
while((<<k)<n)k++;
for(int i=;i<n;i++){
int t=;
for(int j=;j<k;j++)if((<<j)&i)t|=(<<(k-j-));
if(i<t)swap(a[i],a[t]);
}
for(int l=;l<=n;l*=){
int m=l>>;
for(int *p=a;p!=a+n;p+=l){
for(int i=;i<m;i++){
int t=1ll*p[i+m]*o[n/l*i]%MOD;
p[i+m]=(p[i]-t+MOD)%MOD;
p[i]=(p[i]+t)%MOD;
}
}
}
}
void dft(int *a,int n){transform(a,n,o);}
void idft(int *a,int n){
transform(a,n,oi);int v=inv(n);
for(int i=;i<n;i++)a[i]=1ll*a[i]*v%MOD;
}
void pinv(int *F,int *g,int n){
if(n==){g[]=inv(F[]);return;}
pinv(F,g,n>>);n<<=;
init(n);//
for(int i=;i<n/;i++)f[i]=F[i],f[i+n/]=;
dft(f,n);dft(g,n);
for(int i=;i<n;i++)g[i]=1ll*g[i]*(-1ll*f[i]*g[i]%MOD+MOD)%MOD;//1ll
idft(g,n);for(int i=n/;i<n;i++)g[i]=;// }
}
int F[maxn],G[maxn],n,fac[maxn];
int main(){
int n,N=;
scanf("%d",&n);n++;
while(N<n)N*=;
fac[]=;
for(int i=;i<n;i++)fac[i]=1ll*fac[i-]*i%MOD;
for(int i=;i<n;i++)F[i]=((-*inv(fac[i]))%MOD+MOD)%MOD;
F[]++;
ntt::pinv(F,G,N);
int ans=;
for(int i=;i<n;i++)ans=(ans+1ll*G[i]*fac[i]%MOD)%MOD;
printf("%d",ans);
return ;
}

注意:多项式求逆过程中每次都要对不同的n进行一次预处理omega[]。

另一种做法

【算法】斯特林数+NTT

【题解】首先有第二类斯特林数的通项公式。

$s(n,m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^k*C(m,k)*(m-k)^n$

当斯特林数s(n,m)满足m>n时,上述公式计算结果为0,所以第二个Σ可以扩展到n。

$ans=\sum_{i=0}^{n}\sum_{j=0}^{n}s(i,j)*s^j*j!$

代入第二类斯特林数公式。

$ans=\sum_{i=0}^{n}\sum_{j=0}^{n}2^j*j!*\frac{1}{j!}\sum_{k=0}^{j}(-1)^k*\frac{j!}{k!(j-k)!}*(j-k)^i$

通过组合数的分解,向卷积靠拢。

注意到Σi只对最后一个括号有影响,所以移动到最后。

$ans=\sum_{j=0}^{n}2^j*j!\sum_{k=0}^{j}\frac{(-1)^k}{k!}*\frac{\sum_{i=0}^{n}(j-k)^i}{(j-k)!}$

这已经是标准的卷积形式(第二个函数分子是等比数列可以直接计算)。

使用NTT计算。

注意:

1.n=0,只有使0^0=1,斯特林数通项公式才能处理s(0,0)的情况。

2.n=1,等比数列求和公式不能处理Σ1^i即q=1的情况。

所以特殊地,g[0]=1,g[1]=n+1。先计算完再n++。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=,MOD=; int power(int x,int k){
int ans=;
while(k){
if(k&)ans=1ll*ans*x%MOD;
x=1ll*x*x%MOD;
k>>=;
}
return ans;
}
int inv(int x){return power(x,MOD-);}
namespace ntt{
int o[maxn],oi[maxn];
void init(int n){
int x=,g=power(,(MOD-)/n);
for(int k=;k<n;k++){
o[k]=x;oi[k]=inv(o[k]);
x=1ll*x*g%MOD;
}
}
void transform(int *a,int n,int *o){
int k=;
while((<<k)<n)k++;
for(int i=;i<n;i++){
int t=;
for(int j=;j<k;j++)if((<<j)&i)t|=(<<(k-j-));
if(i<t)swap(a[i],a[t]);
}
for(int l=;l<=n;l*=){
int m=l>>;
for(int *p=a;p!=a+n;p+=l){
for(int i=;i<m;i++){
int t=1ll*p[i+m]*o[n/l*i]%MOD;
p[i+m]=(p[i]-t+MOD)%MOD;
p[i]=(p[i]+t)%MOD;
}
}
}
}
void dft(int *a,int n){transform(a,n,o);}
void idft(int *a,int n){
transform(a,n,oi);
int x=inv(n);
for(int i=;i<n;i++)a[i]=1ll*a[i]*x%MOD;
}
}
int n,fac[maxn],f[maxn],g[maxn];
int main(){
scanf("%d",&n);
fac[]=;
for(int i=;i<=n;i++)fac[i]=1ll*fac[i-]*i%MOD;
for(int i=;i<=n;i++)f[i]=1ll*((i&)?MOD-:)*inv(fac[i])%MOD;
for(int i=;i<=n;i++)g[i]=1ll*(-power(i,n+)+MOD)*inv((-i+MOD)%MOD)%MOD*inv(fac[i])%MOD;
g[]=;g[]=n+;//
n++;int N=;//
while(N<n+n)N*=;
ntt::init(N);
ntt::dft(f,N);ntt::dft(g,N);
for(int i=;i<N;i++)f[i]=1ll*f[i]*g[i]%MOD;
ntt::idft(f,N);
int ans=;
for(int i=;i<n;i++)ans=(ans+1ll*power(,i)*fac[i]%MOD*f[i]%MOD)%MOD;
printf("%d",ans);
return ;
}

【BZOJ】4555: [Tjoi2016&Heoi2016]求和 排列组合+多项式求逆 或 斯特林数+NTT的更多相关文章

  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]求和 (多项式求逆)

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

  4. BZOJ 4555 [Tjoi2016&Heoi2016]求和 ——分治 NTT 多项式求逆

    不想多说了,看网上的题解吧,我大概说下思路. 首先考察Stirling的意义,然后求出递推式,变成卷积的形式. 然后发现贡献是一定的,我们可以分治+NTT. 也可以直接求逆(我不会啊啊啊啊啊) #in ...

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

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

  6. 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 ...

  7. [BZOJ 4555][Tjoi2016&Heoi2016]求和

    题意 给定 $n$ , 求下式的值: $$ f(n)= \sum_{i=0}^n\sum_{j=0}^i\begin{Bmatrix}i\\ j\end{Bmatrix}\times 2^j\time ...

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

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

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

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

随机推荐

  1. Swift-自定义类的构造函数

    构造函数类似oc中的init方法默认情况下,创建一个,类会调用一个构造函数即使没写任何构造函数,编译器会默认一个构造函数如果是继承NSObject,可以对构造函数重写 class Person: NS ...

  2. 在服务器中使用 Entity Framework 的 Migration 更新数据库

    在开发环境中,每次我们对要对数据库进行更改,比如增加修改表字段等.改好Entity类后,我们只需在Nuget程序包管理控制台运行 update-database 脚本却可: update-databa ...

  3. (转)Elasticsearch search-guard 插件部署

    我之前写了ELK+shield的部署文档,由于shield是商业收费的,很多人都推崇开源项目search-guard来做ELK的安全组件,准确来说是elasticsearch的安全组件.search- ...

  4. phaser的小游戏的onInputDown问题

    group.inputEnableChildren = true; for (var i = 0; i < 10; i++) {          var sprite = group.crea ...

  5. Bare metal APIs with ASP.NET Core MVC(转)

    ASP.NET Core MVC now provides a true "one asp.net" framework that can be used for building ...

  6. Delphi ADOQuery多个参数重复 改编技巧

    今天看了多年前的一个帖子,发现回答不合理,有些还将其归为delphi的bug.其实主要是没有灵活应用参数. ADOQUERY查询时,这样不行,结果不正确. WITH ADOQUERY1 DO BEGI ...

  7. hdu6415 Rikka with Nash Equilibrium (DP)

    题目链接 Problem Description Nash Equilibrium is an important concept in game theory. Rikka and Yuta are ...

  8. 【uoj#310】[UNR #2]黎明前的巧克力 FWT

    题目描述 给出 $n$ 个数,从中选出两个互不相交的集合,使得第一个集合与第二个集合内的数的异或和相等.求总方案数. 输入 第一行一个正整数 $n$ ,表示巧克力的个数.第二行 $n$ 个整数 $a_ ...

  9. Guardian of Decency UVALive - 3415(最大独立集板题)

    老师在选择一些学生做活动时,为避免学生发生暧昧关系,就提出了四个要求.在他眼中,只要任意两个人符合这四个要求之一,就不可能发生暧昧.现在给出n个学生关于这四个要求的信息,求老师可以挑选出的最大学生数量 ...

  10. 【刷题】BZOJ 1036 [ZJOI2008]树的统计Count

    Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. ...