码迷,mamicode.com
首页 > 其他好文 > 详细

[bzoj4555] [Tjoi2016&Heoi2016]求和

时间:2018-08-09 21:08:14      阅读:129      评论:0      收藏:0      [点我收藏+]

标签:c++   efi   class   its   put   int   esc   bin   isp   


Description

在2016年,佳媛姐姐刚刚学习了第二类斯特林数,非常开心。

现在他想计算这样一个函数的值:\[f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}S(i,j)*2^j*(j!)\]

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)对998244353(7 × 17 × 223 + 1)取模的结果即可。1 ≤ n ≤ 100000

Sample Input
3
Sample Output
87

solution
看到模数,上ntt(最近在学)
然后先推式子\[f(n)=\sum_{i=0}^n\sum_{j=0}^iS(i,j)*2^j*j!\] \[=\sum_{i=0}^n\sum_{j=0}^nS(i,j)*2^j*j!\]
枚举上限变为n是因为i>j时S为0,方便推式子
然后把斯特林数展开,这步不懂的可以上百度,有证明\[=\sum_{i=0}^n\sum_{j=0}^n2^j\sum_{k=0}^j(-1)^k\binom{j}{k}(j-k)^i\]
再把组合数展开
\[=\sum_{i=0}^n\sum_{j=0}^n2^j\sum_{k=0}^j(-1)^k\frac{j!}{k!(j-k)!}(j-k)^i\]
改变一下枚举顺序
\[=\sum_{j=0}^n2^j*j!\sum_{k=0}^{j}\frac{(-1)^k}{k!}*\frac{\sum_{i=0}^{n}(j-k)^i}{(j-k)!}\]
定义
\[g(x)=\frac{(-1)^x}{x!},h(x)=\frac{\sum_{i=0}^nx^i}{x!}\]
然后原式变为
\[f(x)=\sum_{j=0}^n2^j*j!\sum_{k=0}^{j}g(k)*h(j-k)\]
可以发现后面一部分是一个卷积形式
然后直接上ntt
最后
\[c(j)=\sum_{k=0}^{j}g(k)*h(j-k)\]
\[f(x)=\sum_{j=0}^n2^j*j!*c(j)\]
就可以算答案了

note:\[S(n,m)=\frac{1}{m!}\sum_{k=0}^m(-1)^k\binom{m}{k}(m-k)^n\]

这里贴一下代码吧。。

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(3)
#define mod 998244353
#define int long long
#define maxn 2000050
#define read(x) scanf("%lld",&x)
#define write(x) printf("%lld\n",x)
int n,c[maxn],f[maxn],g[maxn],h[maxn],m,nn,pos[maxn],k,Inv,invn;
int qpow(int a,int x){
    int res=1;a%=mod;
    for(;x;x>>=1,a=1ll*a*a%mod)if(x&1)res=1ll*res*a%mod;
    return res;
}
int inv(int x){return qpow(x,mod-2);}
void ntt(int *a,int op){
    for(int i=1;i<n;i++) if(pos[i]>i) swap(a[pos[i]],a[i]);
    for(int i=2;i<=n;i<<=1){
    int wn=qpow(op==1?3:Inv,(mod-1)/i);
    for(int j=0;j<n;j+=i){
        int w=1;
        for(int k=0;k<(i>>1);k++){
        int x=a[k+j]%mod,y=a[(i>>1)+k+j]*w%mod;
        a[k+j]=(x+y)%mod,a[(i>>1)+k+j]=(x-y+mod)%mod;
        w=w*wn%mod;
        }
    }
    }
    if(op==1) return ;
    for(int i=0;i<n;i++) a[i]=a[i]*invn%mod;
}
void solve(){
    Inv=qpow(3,mod-2);
    read(n);g[0]=1;int x=1;h[0]=1,h[1]=n+1;
    for(int i=1;i<=n;i++) g[i]=(-g[i-1]*inv(i)%mod+mod)%mod;
    for(int i=2;i<=n;i++) x=x*i%mod,h[i]=(inv(x)*(1-qpow(i,n+1))%mod*inv(1-i+mod)%mod+mod)%mod;
    nn=n;m=n*2;for(n=1;n<=m;n<<=1)k++;
    for(int i=1;i<=n;i++) pos[i]=(pos[i>>1]>>1)|((i&1)<<(k-1));invn=inv(n);
    ntt(g,1),ntt(h,1);
    for(int i=0;i<n;i++) g[i]=g[i]*h[i]%mod;
    ntt(g,-1);
    x=1;int q=1;int ans=1;
    for(int i=1;i<=nn;i++) x=x*i%mod,q=q*2%mod,ans=(ans+x*q%mod*g[i]%mod)%mod;
    write(ans);
}
#undef int
int main(){solve();}

[bzoj4555] [Tjoi2016&Heoi2016]求和

标签:c++   efi   class   its   put   int   esc   bin   isp   

原文地址:https://www.cnblogs.com/hbyer/p/9451203.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!