zoukankan      html  css  js  c++  java
  • [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
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=100000+5;
    const int mod=998244353;
    const int G=3;
    const int GI=332748118;
    ll qm(ll x,ll y){
        ll ret=1;
        while(y){
            if(y&1) ret=ret*x%mod;
            x=x*x%mod;
            y>>=1;
        }return ret;
    }
    int rev[4*N];
    ll a[4*N],b[4*N];
    int n;
    void NTT(ll *f,int c){
        for(reg i=0;i<n;++i){
            if(rev[i]<i) swap(f[i],f[rev[i]]);
        }
        for(reg p=2;p<=n;p<<=1){
            ll gen;
            if(c==1) gen=qm(G,(mod-1)/p);
            else gen=qm(GI,(mod-1)/p);
            int len=p/2;
            for(reg l=0;l<n;l+=p){
                ll buf=1;
                for(reg k=l;k<l+len;++k){
                    ll tmp=f[k+len]*buf%mod;
                    f[k+len]=(f[k]-tmp+mod)%mod;
                    f[k]=(f[k]+tmp)%mod;
                    buf=buf*gen%mod;
                }
            }
        }
    }
    ll jie[N],inv[N],ni[N];
    int main(){
        rd(n);jie[0]=1;
        for(reg i=1;i<=n;++i) jie[i]=jie[i-1]*i%mod;
        inv[n]=qm(jie[n],mod-2);inv[0]=1;
        for(reg i=n-1;i>=1;--i) inv[i]=inv[i+1]*(i+1)%mod;
        for(reg i=1;i<=n;++i) ni[i]=((mod-mod/i)*ni[mod%i]+mod)%mod;
        for(reg i=0;i<=n;++i){
            if(i&1) a[i]=mod-inv[i];
            else a[i]=inv[i];
            if(i==1) b[i]=n+1;
            else if(i==0) b[i]=1;
            else b[i]=(qm(i,n+1)-1+mod)%mod*qm(i-1,mod-2)%mod*inv[i]%mod;
        }
        int m;
        int lp=n;
        for(m=n+n,n=1;n<=m;n<<=1);
        for(reg i=0;i<n;++i){
            rev[i]=(rev[i>>1]>>1)|((i&1)?n>>1:0);
        }
    //    for(reg i=0;i<n;++i){
    //        cout<<a[i]<<" ";
    //    }cout<<endl;
    //    for(reg i=0;i<n;++i){
    //        cout<<b[i]<<" ";
    //    }cout<<endl;
        
        NTT(a,1);NTT(b,1);
        for(reg i=0;i<n;++i) b[i]=(ll)b[i]*a[i]%mod;
        NTT(b,-1);ll yuan=qm(n,mod-2);
        for(reg i=0;i<n;++i) b[i]=b[i]*yuan%mod;
        ll ans=0;
        for(reg j=0;j<=lp;++j){
           // cout<<" bj "<<j<<" : "<<b[j]<<endl;
            ans=(ans+qm(2,j)*jie[j]%mod*b[j]%mod)%mod;
            //cout<<" ans "<<ans<<endl;
        }
        printf("%lld",ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/28 21:51:13
    */
  • 相关阅读:
    python-局部变量与全局变量作用域
    python-函数(上):函数返回值、函数调用、前向引用
    python-文件读写
    python-输入和输出
    python-模块介绍及os模块的方法
    python-continue和break的区别
    python-for循环
    python-while循环
    python-三元运算和if...else
    python-数据类型(下) :byte、列表、元组、集合
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10197836.html
Copyright © 2011-2022 走看看