zoukankan      html  css  js  c++  java
  • 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_{i=0}^m(-1)^{i}C_{m}^i(m-i)^n ]

    颓柿子

    题目要求求这样一个式子

    [f(n)=sum_{i=0}^nsum_{j=0}^iS_i^j imes2^j imes(j!) ]

    然后我们把第二类斯特林数的通式代入进去

    [f(n)=sum_{i=0}^nsum_{j=0}^iS_i^j imes2^j imes(j!) ]

    得到

    [f(n)=sum_{i=0}^nsum_{j=0}^i frac{1}{j!}sum_{k=0}^j(-1)^{k}C_{j}^k(j-k)^i imes2^j imes(j!)\=sum_{i=0}^nsum_{j=0}^ij! imes2^jsum_{k=0}^jfrac{(-1)^k}{k!} imesfrac{(j-k)^i}{(j-k)!}\=sum_{j=0}^nj! imes2^jsum_{k=0}^{j}frac{(-1)^k}{k!} imesfrac{sum_{i=0}^n(j-k)^i}{(j-k)!} ]

    如果我们设(F(i)=frac{(-1)^k}{k!})(G(i)=frac{sum_{i=0}^n(j-k)^i}{(j-k)!}),则很容易就能看出一个卷积的形式,式子变形成

    [f(n)=sum_{j=0}^nj! imes 2^j sum_{i=0}^j F(i) imes G(j-i) ]

    FFT求后面的式子就行了

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    const int MOD=998244353LL,G=3,invG=332748118;
    int pow(int a,int b){
        int ans=1;
        while(b){
            if(b&1)
                ans=(1LL*ans*a)%MOD;
            a=(1LL*a*a)%MOD;
            b>>=1;
        }
        return (ans%MOD+MOD)%MOD;
    }
    void FFT(int *a,int opt,int n){
        int lim=0;
        while((1<<lim)<n)
            lim++;
        for(int i=0;i<n;i++){
            int t=0;
            for(int j=0;j<lim;j++)
                if((i>>j)&1)
                    t|=(1<<(lim-j-1));
            if(i<t)
                swap(a[t],a[i]);
        }
        for(int i=2;i<=n;i<<=1){
            int len=i/2;
            int tmp=pow((opt)?G:invG,(MOD-1)/i);
            for(int j=0;j<n;j+=i){
                int arr=1;
                for(int k=j;k<j+len;k++){
                    int t=(a[k+len]*arr)%MOD;
                    a[k+len]=((a[k]-t)%MOD+MOD)%MOD;
                    a[k]=(a[k]+t)%MOD;
                    arr=(arr*tmp)%MOD;
                }
            }
        }
        if(opt==0){
            int invn=pow(n,MOD-2);
            for(int i=0;i<n;i++)
                a[i]=(a[i]*invn)%MOD;
        }    
    }
    int a[300100],b[300100],n;
    int jc[300100],inv[300100];
    void init(void){
        jc[0]=inv[0]=1;
        for(int i=1;i<=n;i++){
            jc[i]=jc[i-1]*i%MOD;
            inv[i]=pow(jc[i],MOD-2);
        }
    }
    int f(int x){
        return ((((x&1)?-1:1)%MOD+MOD)%MOD*(inv[x]))%MOD;
    }
    int g(int x){
        if(x==1)
            return n+1;
        return ((((pow(x,n+1)-1)%MOD+MOD)%MOD)*pow(x-1+MOD,MOD-2)%MOD)*inv[x]%MOD;
    }
    signed main(){
        scanf("%lld",&n);
        // printf("n=%d
    ",n);
        init();
        for(int i=0;i<=n;i++)
            a[i]=f(i),b[i]=g(i);
        // for(int i=0;i<=n;i++)
        //     printf("f(%lld)=%lld g(%lld)=%lld
    ",i,a[i],i,b[i]);
        int lx=1;
        while(lx<=(n+n))
            lx<<=1;
        FFT(a,1,lx);
        FFT(b,1,lx);
        for(int i=0;i<lx;i++)
            a[i]=(a[i]*b[i])%MOD;
        FFT(a,0,lx);
        // for(int i=0;i<=n;i++)
        //     printf("f*g(%lld)=%lld
    ",i,a[i]);
        int ans=0;
        for(int i=0,j=1;i<=n;i++,j=(j+j)%MOD)
            ans=(ans+j*jc[i]%MOD*a[i]%MOD)%MOD;
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    quick cocos2dx 播放序列帧动画的实现
    PS学习笔记
    python自学笔记(十一)关于函数及书写格式
    python自学笔记(十)语句与数据结构应用
    python自学笔记(九)python练习题
    python自学笔记(八)python语句
    python自学笔记(七)排序与多级排序
    python自学笔记(六)二进制与位移
    python自学笔记(五)python文本操作
    python自学笔记(四)python基本数据类型之元组、集合、字典
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10435299.html
Copyright © 2011-2022 走看看