[题解] LuoguP4091 [HEOI2016/TJOI2016]求和

传送门

首先我们来看一下怎么求\(S(m,n)\)。

注意到第二类斯特林数的组合意义就是将\(m\)个不同的物品放到\(n\)个没有区别的盒子里,不允许有空盒子的方案数。

那么将\(m\)个不同的物品随便扔到\(n\)个盒子里的方案数就是\(n^m\),这里盒子也有区别了。

那么枚举有多少盒子有物品,然后斯特林数安排一下,注意到这是的盒子是没有区别的,再排列就好了,即
\[
n^m=\sum\limits_{i=0}^n \binom{n}{i}S(m,i)i!
\]
但我们要求的是\(S\),这里又有组合数,直接二项式反演,,得到
\[
n! \times S(m,n)=\sum\limits_{i=0}^n (-1)^{n-i}\binom{n}{i}i^m
\]
所以
\[
S(m,n) = \frac{1}{n!}\sum\limits_{i=0}^n (-1)^{n-i} \binom{n}{i} i^m
\]

然后再来看题目里的柿子:
\[
\sum\limits_{i=0}^n\sum\limits_{j=0}^i S(i,j) \times 2^j \times (j!)
\]
我也不知道它为什么长成这样...

由于\(j>i\)时\(S(i,j)=0\),所以\(j\)完全可以到\(n\),然后再吧\(S(i,j)\)换成上面的求和形式
\[
\sum\limits_{i=0}^n\sum\limits_{j=0}^n 2^j \sum\limits_{k=0}^j (-1)^{j-k}\binom{j}{k} k^i
\]

\[
= \sum\limits_{j=0}^n 2^j \sum\limits_{k=0}^j (-1)^{j-k}\binom{j}{k} \sum\limits_{i=0}^n k^i
\]

\[
= \sum\limits_{j=0}^n 2^j \sum\limits_{k=0}^j (-1)^{j-k}\frac{j!}{k!(j-k)!} \sum\limits_{i=0}^n k^i
\]

\[
= \sum\limits_{j=0}^n 2^j\times (j!) \sum\limits_{k=0}^j \frac{(-1)^{j-k}}{(j-k)!} \times (k!\sum\limits_{i=0}^n k^i)
\]

后面已经是一个卷积的形式了,具体的,令
\[
f_i = \frac{(-1)^i}{i!}
\]

\[
g_i = i!\sum\limits_{k=0}^n i^k = i! \times \frac{(i^{k+1}-1)}{i-1}
\]

需要特判\(g_1=n+1\),把\(f,g\)卷起来求和就好了

\(Code:\)

#include <bits/stdc++.h>
using namespace std;
const int N=3e5+10,P=998244353;
inline int fpow(int x,int y,int mod=P)
{
    int ret=1; for(x%=mod;y;y>>=1,x=1ll*x*x%mod)
        if(y&1) ret=1ll*ret*x%P;
    return ret;
}
const int gen=3,igen=fpow(gen,P-2);
inline int add(int x,int y,int mod=P){return (x+=y)>=mod?x-mod:x;}
inline int sub(int x,int y,int mod=P){return (x-=y)<0?x+mod:x;}
inline int normal(int x,int mod=P){return x<0?x+mod:x;}
namespace Poly
{
    int rev[N];
    void init(int n)
    {
        for(int i=0;i<n;i++)
            rev[i]=rev[i>>1]>>1|((i&1)?n>>1:0);
    }
    void ntt(int *f,int n,int flg)
    {
        for(int i=0;i<n;i++)
            if(rev[i]<i) swap(f[i],f[rev[i]]);
        for(int len=2,k=1;len<=n;len<<=1,k<<=1)
        {
            int wn=fpow(flg==1?gen:igen,(P-1)/len);
            for(int i=0;i<n;i+=len)
                for(int j=i,w=1;j<i+k;j++,w=1ll*w*wn%P)
                {
                    int tmp=1ll*f[j+k]*w%P;
                    f[j+k]=sub(f[j],tmp),f[j]=add(f[j],tmp);
                }
        }
        if(flg==-1)
        {
            int inv=fpow(n,P-2);
            for(int i=0;i<n;i++) f[i]=1ll*f[i]*inv%P;
        }
    }
}
using Poly::ntt;
int f[N],g[N],n;
int pw2[N],inv[N],ifac[N],fac[N];
int main()
{
    scanf("%d",&n);
    inv[1]=ifac[0]=ifac[1]=1;
    pw2[0]=1,pw2[1]=2; fac[0]=fac[1]=1;
    for(int i=2;i<=n;i++)
    {
        inv[i]=1ll*inv[P%i]*(P-P/i)%P;
        ifac[i]=1ll*ifac[i-1]*inv[i]%P;
        pw2[i]=2ll*pw2[i-1]%P;
        fac[i]=1ll*fac[i-1]*i%P;
    }
    for(int i=0;i<=n;i++)
    {
        f[i]=1ll*((i&1)?P-1:1)*ifac[i]%P;
        if(i==1) g[i]=n+1;
        else g[i]=1ll*sub(fpow(i,n+1),1)*ifac[i]%P*fpow(i-1,P-2)%P;
    }
    int limit=1; while(limit<=n*2)limit<<=1;
    Poly::init(limit);
    ntt(f,limit,1),ntt(g,limit,1);
    for(int i=0;i<limit;i++) f[i]=1ll*f[i]*g[i]%P;
    ntt(f,limit,-1);
    int ans=0;
    for(int i=0;i<=n;i++) ans=add(ans,1ll*pw2[i]*fac[i]%P*f[i]%P);
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/wxq1229/p/12331797.html

时间: 2024-11-09 10:29:10

[题解] LuoguP4091 [HEOI2016/TJOI2016]求和的相关文章

P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数,ntt)

题面:https://www.luogu.org/problem/P4091 题解:\[\begin{array}{l}f(n) = \sum\limits_{i = 0}^n {\sum\limits_{j = 0}^i {{\rm{S}}(i,j) \cdot {2^{\rm{j}}} \cdot j!} } \\ = \sum\limits_{i = 0}^n {\sum\limits_{j = 0}^n {{\rm{S}}(i,j) \cdot {2^{\rm{j}}} \cdot j!

[HEOI2016/TJOI2016]求和

Discription 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ? S(i ? 1, j) + S(i ? 1, j ? 1), 1 <= j <= i ? 1. 边界条件为:S(i, i) = 1(0 <= i), S(i, 0) = 0(1 <= i) 你能帮帮他吗? Input 输入只有一个正整数 Output 输出f(n). 由于结果会很大,输出f(n

luogu P4091 [HEOI2016/TJOI2016]求和

传送门 这一类题都要考虑推式子 首先,原式为\[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}S(i,j)*2^j*j!\] 可以看成\[f(n)=\sum_{j=0}^{n}2^j*j!\sum_{i=j}^{n}S(i,j)\] 又因为\[S(i,j)=\frac{1}{j!}\sum_{k=0}^{j}(-1)^k*\binom{j}{k}*(j-k)^i\] 所以\[f(n)=\sum_{j=0}^{n}2^j*j!\sum_{i=0}^{n}\frac{1}{j!}

[HEOI2016/TJOI2016]求和——第二类斯特林数

给你斯特林数就换成通项公式,给你k次方就换成斯特林数 考虑换成通项公式之后,组合数没有什么好的处理方法 直接拆开,消一消阶乘 然后就发现了(j-k)和k! 往NTT方向靠拢 然后大功告成 其实只要想到把斯特林公式换成通项公式,考虑用NTT优化掉(j-k)^i 后面都是套路了. #include<bits/stdc++.h> #define reg register int #define il inline #define numb (ch^'0') #define int long long

P4091 [HEOI2016/TJOI2016]求和

留待警戒 FFT的时候长度要写的和函数里一样啊XD 瞎扯 这是个第二类斯特林数的理性愉悦颓柿子题目 颓柿子真的是让我hi到不行啦(才没有) 前置芝士 一个公式 \[ \sum_{i=0}^n t^i = \frac{t^{n+1}-1}{t-1} \] 第二类斯特林数 第二类斯特林数的是指把n个对象放到m个集合里面的方案数 其递推式是 \[ S_{n}^{m}=S_{n-1}^{m-1}+mS_{n-1}^{m} \] 容斥原理的得到的通式 \[ S_n^m=\frac{1}{m!}\sum_{

[HEOI2016/TJOI2016]求和 斯特林数 + NTT

Description 计算函数的值 \[f(n) = \sum \limits_{i=0}^{n} \sum \limits_{j=0}^{i} 2^j \times j! \times S(i,j)\] Solution 大家好,我是练习推柿子半天的个人练习生\(newbielyx\). \[ f(n) = \sum \limits_{i=0}^{n} \sum \limits_{j=0}^{i} 2^j \times j! \times S(i,j) \] \[ = \sum \limit

[HEOI2016/TJOI2016]排序 解题报告

[HEOI2016/TJOI2016]排序 题意 给出一个大小为 \(n\) 的排列, 对这个排列进行 \(m\) 次操作, 操作分为以下两种, 0 l r 表示将区间 \([l,r]\) 的数升序排序. 1 l r 表示将区间 \([l,r]\) 的数降序排序. 询问 \(m\) 次操作后下标为 \(q\) 的数字. 思路 不看题解打死也想不出来系列 考虑二分答案. 设当前二分的答案为 \(mid\), 把原排列中 大于等于 \(mid\) 的数标记为 \(1\), 小于 \(mid\) 的数

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树)

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树) 题面 给出一个长度为\(n\)的字符串\(s\),以及\(m\)组询问.每个询问是一个四元组\((a,b,c,d)\),问\(s[a,b]\)的所有子串和字符串\(s[c,d]\)的最长公共前缀长度的最大值. \(n,m \leq 10^5\) 分析 显然答案有单调性.首先我们二分答案\(mid\),考虑如何判定. 如果mid这个答案可行,那么一定存在一个后缀x,它的开头在\([a,

题解 P4093 【[HEOI2016/TJOI2016]序列】

这道题原来很水的? noteskey 一开始以为是顺序的 m 个修改,然后选出一段最长子序列使得每次修改后都满足不降 这 TM 根本不可做啊! 于是就去看题解了,然后看到转移要满足的条件的我发出了黑人问号... 然后才发现原来是求的子序列是满足任意一次修改后不降... 于是列出两(san)个条件式子,就可以 CDQ 切掉了 QWQ \(j<i\) \(a_j<min_i\) \(max_j<a_i\) 这里的 max 和 min 就是某个位置上出现过的最 大/小 值 watch out