• 「PER #2」2048


    题目

    点这里看题目。

    Public Judge 是新出来的 OJ,所以可能认不得。

    不过没关系,根据 p_b_p_b 的说法,上面的题基本上都是搬的

    分析

    首先,可以忽略每次加入的“位置”,因为我们始终可以保证所有的数都排在前缀上。

    其次,我们注意到,如果新来的数大于当前最靠后的那个数,则最终效果是原有前缀全部被丢弃;否则,我们如果保证新来的数总是小于等于最靠后的那个数,则最终效果是进行二进制的累加

    所以,对于当前的一个活跃(即会影响累加结果)的前缀而言,它一定是单调递减的。这样的话,只要不进位,我们可以认为已有的数对于之后的数没有后效性。根据这个性质,我们可以将这个前缀的形成过程,看作是每次经过若干步,在这个前缀的末尾加入了一个新的数

    那么,首先考虑一个数出现的概率。由于没有步数限制,我们只需要记录 \(f_{i,j}\),表示长度为 \(i\) 的序列中,经过若干步,在头部产生一个 \(2^j\) 的概率。容易得到它的转移方程:

    \[f_{i,j}=[j \le m]p_{j+1}+f_{i,j-1}f_{i-1,j-1} \]

    转移的逻辑是,要么是直接生成 \(2^j\),要么先后生成两个 \(2^{j-1}\)(后面的生成过程不会受前面的那个影响),最后再合并。

    而后,利用期望的线性性拆开贡献,则我们只需要考虑某个前缀的出现概率,直接一边构造前缀形态一边 DP。设 \(g_{i,j}\) 表示经过若干步后,生成一个长度为 \(i\) 的前缀,以 \(2^j\) 结尾的概率。倒腾一下也可以得到转移方程:

    \[g_{i,j}=\sum_{k>j}g_{i-1,k}f_{n-i+1,j}+\sum_{k<j}g_{i-1,k}\prod_{s=k+1}^jp_s\prod_{t=s}^{j-1}f_{n-i,t} \]

    转移逻辑是,分类讨论前缀 \([1,i-1]\)

    1. 如果 \(i-1\) 上的数大于 \(2^j\),则前缀 \([1,i-1]\) 不会影响第 \(i\) 个数的产生,直接用 \(f\) 计算;

    2. 如果 \(i-1\) 上的数小于 \(2^j\),根据之前的分析,第 \(i\) 个数的初始值 \(2^s\) 必须大于第 \(i-1\) 个,才能让前缀 \([1,i-1]\) 失效;之后,还需要从小到大产生若干个数,来将 \(2^s\) 提升到 \(2^j\)

      这一部分其实比较类似于限制第一个数的 \(f\) 的转移。

    朴素转移为 \(O(n^3)\),不难优化到 \(O(n^2)\)

    小结:

    1. 这道题提供了一个基础思路:操作过程比较复杂的模型,可以将连续的操作过程拆分成若干个步骤来考虑

    2. 另外一方面,既然操作过程很复杂,也应该抓住较为简洁的“生成的前缀”这一部分来考虑。

    代码

    #include <cstdio>
    
    #define rep( i, a, b ) for( int i = (a) ; i <= (b) ; i ++ )
    #define per( i, a, b ) for( int i = (a) ; i >= (b) ; i -- )
    
    const int mod = 998244353;
    const int MAXN = 4005;
    
    template<typename _T>
    void read( _T &x ) {
    	x = 0; char s = getchar(); bool f = false;
    	while( ! ( '0' <= s && s <= '9' ) ) { f = s == '-', s = getchar(); }
    	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
    	if( f ) x = -x;
    }
    
    template<typename _T>
    void write( _T x ) {
    	if( x < 0 ) putchar( '-' ), x = -x;
    	if( 9 < x ) write( x / 10 );
    	putchar( x % 10 + '0' );
    }
    
    int f[MAXN][MAXN], g[MAXN][MAXN];
    
    int pw[MAXN];
    int P[MAXN];
    
    int N, M;
    
    inline int Qkpow( int, int );
    inline int Inv( const int &a ) { return Qkpow( a, mod - 2 ); }
    inline int Mul( int x, const int &v ) { return 1ll * x * v % mod; }
    inline int Sub( int x, const int &v ) { return ( x -= v ) < 0 ? x + mod : x; }
    inline int Add( int x, const int &v ) { return ( x += v ) >= mod ? x - mod : x; }
    
    inline int& MulEq( int &x, const int &v ) { return x = 1ll * x * v % mod; }
    inline int& SubEq( int &x, const int &v ) { return ( x -= v ) < 0 ? ( x += mod ) : x; }
    inline int& AddEq( int &x, const int &v ) { return ( x += v ) >= mod ? ( x -= mod ) : x; }
    
    inline int Qkpow( int base, int indx ) {
    	int ret = 1;
    	while( indx ) {
    		if( indx & 1 ) MulEq( ret, base );
    		MulEq( base, base ), indx >>= 1;
    	}
    	return ret;
    }
    
    int main() {
    	int su = 0;
    	read( N ), read( M );
    	rep( i, 0, M - 1 ) read( P[i] ), AddEq( su, P[i] );
    	su = Inv( su );
    	rep( i, 0, M - 1 ) MulEq( P[i], su );
    	rep( i, 1, N ) rep( j, 0, N + M ) {
    		if( j < M ) f[i][j] = P[j];
    		if( j > 0 ) AddEq( f[i][j], Mul( f[i][j - 1], f[i - 1][j - 1] ) );
    	}
    	int ans = 0; g[0][N + M] = 1;
    	pw[0] = 1; rep( i, 1, N + M + 1 ) pw[i] = Mul( pw[i - 1], 2 );
    	rep( i, 1, N ) {
    		int su = 0, contri = 0;
    		per( j, N + M, 0 ) {
    			AddEq( g[i][j], Mul( su, f[N - i + 1][j] ) );
    			AddEq( su, g[i - 1][j] );
    		}
    		su = g[i - 1][0];
    		rep( j, 1, N + M ) {
    			MulEq( contri, f[N - i][j - 1] );
    			AddEq( contri, Mul( su, P[j] ) );
    			AddEq( g[i][j], contri );
    			AddEq( su, g[i - 1][j] );
    		}
    		rep( j, 0, N + M )
    			AddEq( ans, Mul( g[i][j], Mul( f[N - i][j], pw[j + 1] ) ) );
    	}
    	write( ans ), putchar( '\n' );
    	return 0;
    }
    
  • 相关阅读:
    Django会话之session(手动设置)
    Django model字段类型参考列表
    Django会话之cookie(手动设置)
    Java AES加密
    Java AES加密
    Java JDBC
    Java JDBC
    Java-Map
    Java-Map
    Java-螺旋方阵
  • 原文地址:https://www.cnblogs.com/crashed/p/16246616.html
Copyright © 2020-2023  润新知