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!} }
\end{array}\]

把公式\[S(n,m) = \frac{{\sum\limits_{i = 0}^m {{{( - 1)}^i}{\rm{\cdot}}C_m^i} {\rm{\cdot}}{{(m - i)}^n}}}{{m!}}\]带进去

则\[{\rm{\backslash begin\{ array\} \{ l\} n\backslash begin\{ array\} \{ *\{ 20\} \{ l\} \} }}f(n) = \sum\limits_{i = 0}^n {\sum\limits_{j = 0}^n {{\rm{S}}(i,j) \cdot {2^{\rm{j}}} \cdot j!}  = \sum\limits_{i = 0}^n {\sum\limits_{j = 0}^n {\sum\limits_{k = 0}^j {\frac{{{{( - 1)}^k}}}{{k!}} \cdot \frac{{{{(j - k)}^i}}}{{(j - k)!}}}  \cdot {{\rm{2}}^{\rm{j}}}{\rm{\cdotj}}!} } } {\rm{n\{ }} = \sum {\rm{\_}}j = {\rm{\^}}n{\rm{ \{ }}{2^j}{\rm{\cdotj}}!\sum {\rm{\_}}k = 0{\rm{\^}}j{\rm{ \{ }}\sum {\rm{\_}}i = 0{\rm{\^}}n{\rm{ \{ }}\frac{{{{( - 1)}^k}}}{{k!}} \cdot \frac{{{{(j - k)}^i}}}{{(j - k)!}} = \sum {\rm{\_}}j = {\rm{\^}}n{\rm{ \{ }}{2^j}{\rm{\cdot}}j!\sum {\rm{\_}}k = 0{\rm{\^}}j{\rm{ \{ \backslash frac\{ \{ \{ }}( - 1){\rm{\^\{ \^}}k{\rm{\} \} \} \} }}k! \cdot {\rm{\} }}\frac{{\sum\limits_{i = 0}^n {{{(j - k)}^i}} }}{{(j - k)!}}{\rm{\}  \}  \}  \}  \} n\backslash end\{ array\} \backslash \backslash  = }}\sum {\rm{\_}}j = {\rm{\^}}n{\rm{ \{ }}{2^j}{\rm{\cdot}}j!\sum {\rm{\_}}k = 0{\rm{\^}}j{\rm{ \{ \backslash frac\{ \{ \{ }}( - 1){\rm{\^\{ \^}}k{\rm{\} \} \} \} }}k! \cdot {\rm{\} }}\frac{{{{(j - k)}^{n + 1}} - 1}}{{(j - k)! \cdot (j - k - 1)}}{\rm{\} n\backslash end\{ array\} }}\]

令\[\begin{array}{l}
h(x) = \frac{{{{( - 1)}^x}}}{{x!}}\\
g(x) = \frac{{{x^{n + 1}} - 1}}{{x!{\rm{\cdot(x - 1)}}}}
\end{array}\]

后面的就是这两个的卷积,直接上ntt就行了

#include<bits/stdc++.h>
#define ms(x) memset(x,0,sizeof(x))
#define sws ios::sync_with_stdio(false)
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
const double pi=acos(-1.0);
const ll mod=998244353;///通常情况下的模数,
const ll g=3;///模数的原根998244353,1004535809,469762049
ll qpow(ll a,ll n,ll p){
    ll ans=1;
    while(n){
        if(n&1) ans=ans*a%p;
        n>>=1;
        a=a*a%p;
    }
    return ans;
}
int rev[maxn];
void ntt(ll a[],int n,int len,int pd){
    rev[0]=0;
    for(int i=1;i<n;i++){
        rev[i]=(rev[i>>1]>>1 | ((i&1)<<(len-1)));
        if(i<rev[i]) swap(a[i],a[rev[i]]);
    }
    for(int mid=1;mid<n;mid<<=1){
        ll wn=qpow(g,(mod-1)/(mid*2),mod);///原根代替单位根
        if(pd==-1) wn=qpow(wn,mod-2,mod);///逆变换则改成逆元
        for(int j=0;j<n;j+=2*mid){
            ll w=1;
            for(int k=0;k<mid;k++){
                ll x=a[j+k],y=w*a[j+k+mid]%mod;
                a[j+k]=(x+y)%mod;
                a[j+k+mid]=(x-y+mod)%mod;
                w=w*wn%mod;
            }
        }
    }
    if(pd==-1){
        ll inv=qpow(n,mod-2,mod);
        for(int i=0;i<n;i++){
            a[i]=a[i]*inv%mod;

        }
    }
}
ll a[maxn],b[maxn],c[maxn];
void solve(int n,int m){
    int len=0,up=1;
    while(up<=n+m) up<<=1,len++;
    ntt(a,up,len,1);
    ntt(b,up,len,1);
    for(int i=0;i<up;i++) c[i]=1ll*a[i]*b[i]%mod;
    ntt(c,up,len,-1);
}
ll fa[maxn];
int main(){
    int n,m;
    sws;
    cin>>n;
    fa[0]=1;
    a[0]=1;
    b[0]=1;
    for(int i=1;i<=n;i++){
        fa[i]=1ll*fa[i-1]*i%mod;
        int t=(i&1)==1?-1:1;
        a[i]=(t*qpow(fa[i],mod-2,mod)+mod)%mod;
        if(i==1) b[1]=n+1;
        else {
            b[i]=(qpow(i,n+1,mod)-1+mod)%mod*qpow(1ll*(i-1)*fa[i]%mod,mod-2,mod)%mod;
        }
    }
    solve(n,n);
    ll ans=0;
    for(ll i=0;i<=n;i++){
        ans=(ans+qpow(2,i,mod)*fa[i]%mod*c[i]%mod)%mod;
    }
    cout<<ans<<endl;
}

原文地址:https://www.cnblogs.com/azznaz/p/11546388.html

时间: 2024-10-07 18:33:17

P4091 [HEOI2016/TJOI2016]求和(第二类斯特林数,ntt)的相关文章

[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

BZOJ4555 [Tjoi2016&amp;Heoi2016]求和 【第二类斯特林数 + NTT】

题目 在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) 你能帮帮他吗? 输入格式 输入只有一个正整数 输出格式 输出f(n).由于结果会很大,输出f(n)对998244353(7

bzoj 5093 图的价值 —— 第二类斯特林数+NTT

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5093 每个点都是等价的,从点的贡献来看,得到式子: \( ans = n * \sum\limits_{d=0}^{n-1} d^{k} * 2^{C_{n-1}^{2}} * C_{n-1}^{d} \) 使用 \( n^{k} = \sum\limits_{i=0}^{k} S(k,i) * i! *C_{n}^{i} \) 得到 \( ans = n * \sum\limits_{d

bzoj5093:图的价值(第二类斯特林数+NTT)

传送门 首先,题目所求为\[n\times 2^{C_{n-1}^2}\sum_{i=0}^{n-1}C_{n-1}^ii^k\] 即对于每个点\(i\),枚举它的度数,然后计算方案.因为有\(n\)个点,且关于某个点连边的时候剩下的边都可以随便连,所以有前面的两个常数 所以真正要计算的是\[\sum_{i=0}^{n-1}C_{n-1}^ii^k\] 根据第二类斯特林数的性质,有\[i^k=\sum_{j=0}^iS(k,j)\times j!\times C_i^j\] 然后带入,得\[\s

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

[Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 679  Solved: 534[Submit][Status][Discuss] Description 在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心. 现在他想计算这样一个函数的值: S(i, j)表示第二类斯特林数,递推公式为: S(i, j) = j ∗ S(i − 1, j) + S(i − 1, j − 1), 1 <= j &l

【BZOJ 4555】[Tjoi2016&amp;Heoi2016]求和 NTT+第二类斯特林数

用到第二类斯特林数的性质,做法好像很多,我打的是直接ntt,由第二类斯特林数的容斥公式可以推出,我们可以对于每一个i,来一次ntt求出他与所有j组成的第二类斯特林数的值,这个时候我们是O(n^2logn)的,还不如暴力,但是我们发现,对于刚刚提到的容斥的式子,将其化为卷积形式后,其一边的每一项对于每一个i都相同,另一边的每一项是对于所有的i形成一个n项的等比数列,这样我们可以把成等比数列的一边求和,用固定的一边去卷他们的和,这时候的答案的每一项就是所有的i的这一项的和,然后我们再O(n)乘上阶乘

【BZOJ4555】求和(第二类斯特林数,组合数学,NTT)

[BZOJ4555]求和(第二类斯特林数,组合数学,NTT) 题面 BZOJ 题解 推推柿子 \[\sum_{i=0}^n\sum_{j=0}^iS(i,j)·j!·2^j\] \[=\sum_{i=0}^n\sum_{j=0}^nS(i,j)·j!·2^j\] \[=\sum_{i=0}^n\sum_{j=0}^nj!·2^j(\frac{1}{j!}\sum_{k=0}^j(-1)^k·C_j^k·(j-k)^i)\] \[=\sum_{j=0}^n2^j\sum_{k=0}^j(-1)^k

HDU 4045 Machine scheduling (第二类斯特林数+DP)

A Baidu's engineer needs to analyze and process large amount of data on machines every day. The machines are labeled from 1 to n. On each day, the engineer chooses r machines to process data. He allocates the r machines to no more than m groups ,and

奇怪的数学题(51nod1847)——min_25筛+杜教筛+第二类斯特林数

题面 51nod1847 解析   定义$f(i)$为$i$的次大因数,特别地$f(1)=0$  那么我们就是去求$$\sum_{i=1}^{n}\sum_{j=1}^{n}f^{m}(gcd(i, j))$$ 这种东西的套路就是枚举$gcd$然后用欧拉函数处理, \begin{align*}\sum_{i=1}^{n}\sum_{j=1}^{n}f^{m}(gcd(i, j)) &= \sum_{i=1}^{n}\sum_{j=1}^{\left \lfloor \frac{n}{i}\rig

Gym 101147G 第二类斯特林数

大致题意: n个孩子,k场比赛,每个孩子至少参加一场比赛,且每场比赛只能由一个孩子参加.问有多少种分配方式. 分析: k>n,就无法分配了. k<=n.把n分成k堆的方案数乘以n的阶乘.N分成k堆得方案数即第二类斯特林数 http://blog.csdn.net/acdreamers/article/details/8521134 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll