zoukankan      html  css  js  c++  java
  • HDU 5322 Hope

    HDU 5322 Hope

    考虑 $ dp[n] $ 表示 长度为 $ n $ 的所有排列的答案。

    首先,对于一个排列来说,如果最大值在 $ i $ 位置,那么前 $ i - 1 $ 个数必然与 $ i $ 在一个联通块,且必然不会与 $ i $ 后面的数字在一个连通块。

    那么考虑一种常用的排列的处理技巧,考虑将 $ n $ 插入 $ 1 dots n-1 $ 的一个排列,比如插入的位置是 $ i $ 那么 $ i + 1 dots n $ 相当于又是一个排列,而 $ 1 dots i - 1 $ 的方案数是 $ A_{n-1}^{i-1} $ 所以答案就是

    $ dp[n] = displaystyle sum_{i=1}^n A_{n-1}^{i-1} i^2 dp[n - i] $

    这个式子看起来就很分治FFT。

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #define ll long long
    using namespace std;
    #define P 998244353
    #define MAXN (1 << 19) + 12
    int n;
    int a[MAXN];
    int Pow(int x,int y) {
        int res=1;
        while(y) {
            if(y&1) res=res*(ll)x%P;
            x=x*(ll)x%P,y>>=1;
        }
        return res;
    }
    int wn[2][MAXN];
    void getwn(int l) {
        for(int i=1;i<(1<<l);i<<=1) {
            int w0=Pow(3,(P-1)/(i<<1)),w1=Pow(3,P-1-(P-1)/(i<<1));
            wn[0][i]=wn[1][i]=1;
            for(int j=1;j<i;++j)
                wn[0][i+j]=wn[0][i+j-1]*(ll)w0%P,
                        wn[1][i+j]=wn[1][i+j-1]*(ll)w1%P;
        }
    }
    int rev[MAXN];
    void getr(int l) { for(int i=1;i<(1<<l);++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<l-1); }
    void NTT(int *A,int len,int f) {
        for(int i=0;i<len;++i) if(rev[i]<i) swap(A[i],A[rev[i]]);
        for(int l=1;l<len;l<<=1)
            for(int i=0;i<len;i+=(l<<1))
                for(int k=0;k<l;++k) {
                    int t1=A[i+k],t2=A[i+l+k]*(ll)wn[f][l+k]%P;
                    A[i+k]=(t1+t2)%P;
                    A[i+l+k]=(t1-t2+P)%P;
                }
        if( f == 1 ) for(int inv=Pow(len,P-2),i=0;i<len;++i) A[i]=A[i]*(ll)inv%P;
    }
    int f[MAXN];
    int A[MAXN] , B[MAXN];
    int J[MAXN] , invJ[MAXN];
    void CDQ(int *a,int *b,int l,int r){
        if( l == r ) return;
        int m = l + r >> 1;
        CDQ( a , b , l , m );
        int p = 1 , len = 0;
        while( p <= ( r - l + 1 ) * 2 ) p <<= 1 , ++ len;
        getr( len ) , getwn( len );
        for( int i = 0 ; i < p ; ++i ) A[i] = B[i] = 0;
        for( int i = l ; i <= m ; ++i ) A[i - l] = 1ll * a[i] * invJ[i] % P;
        for( int i = 0 ; i <= r - l ; ++i ) B[i] = 1ll * i * i % P;
        NTT( A , p , 0 ) , NTT( B , p , 0 );
        for( int i = 0 ; i < p ; ++i ) A[i] = 1ll * A[i] * B[i] % P;
        NTT( A , p , 1 );
        for( int i = m + 1 ; i <= r ; ++i ) a[i] = ( a[i] + 1ll * J[i - 1] * A[i-l] % P ) % P;
        CDQ( a , b , m + 1 , r );
    }
    int main() {
        J[0] = invJ[0] = 1;
        for( int i = 1 ; i < MAXN ; ++ i ) J[i] = 1ll * J[i - 1] * i % P , invJ[i] = Pow( J[i] , P - 2 );
        f[0] = 1;
        CDQ( f , a , 0 , 100006 );
        int x;
        while( cin >> x ) printf("%d
    ",f[x]);
    }
    
  • 相关阅读:
    make -j 8参数的作用
    使用请求头认证来测试需要授权的 API 接口
    查看Linux系统的平均负载
    服务器负载均衡的基本功能和实现原理
    Oracle RAC学习笔记:基本概念及入门
    详解物化视图(汇总比较有用的资料)
    程序优化注意的一些点
    PR 审批界面增加显示项方法
    Most Common Solutions to FRM-41839 and .tmp Files Not Being Deleted
    APPCORE Routine APIs
  • 原文地址:https://www.cnblogs.com/yijan/p/hdu5322.html
Copyright © 2011-2022 走看看