zoukankan      html  css  js  c++  java
  • Solution -「ARC 124E」Pass to Next

    (mathcal{Description})

      Link.

      有 (n) 个人站成一个环,初始时第 (i) 个人手里有 (a_i) 个球。第 (i) 个人可以将自己手中任意数量的求给第 (i+1) 个人,第 (n) 个人则可以给第 (1) 个人。设所有人同时进行一次传球后,第 (i) 个人手里有 (b_i) 个球,并令 (B) 为所有可能的 (lang b_n ang) 构成的集合,求

    [ sum_{lang b_n angin B}prod_{xinlang b_n ang}x pmod{998244353}. ]

      (nle10^5)

    (mathcal{Solution})

      首先有一个明显而重要的结论:存在某个人没有给别人球的传球方案一一对应了所有可能的 (lang b_n ang)

      方法一 从暴力 DP 入手。枚举最小的 (i=x),使得 (x) 没有向 (x+1) 传球,此时令 (f(i,j)) 表示第 (i) 个人给出 (j) 个球时,(x+1sim i) 这一段人的 (b) 值的乘积之和。转移时记得讨论当前的 (i) 能否不给下一个人球。

      写出转移式,似乎很难优化。这时不妨想一想,DP 欲求得的目标是什么?(f(i,j))?并不,应是 (sum_j f(i,j))。回头看一眼转移,发现我们能直接将转移施加在 (sum_j f(i,j)) 上,状态中的 (j) 根本不需要!

      下一步优化比较简单:两种情况的转移均能写成 (2 imes2) 的矩阵,求一求前缀积之类的就内求出答案了。复杂度 (mathcal O(n))


      方法二 从组合意义入手。(prod b_i) 即传完求后,每个人再从手里的球里选出一个的方案数。那么令 (f(i,0/1)) 表示考虑了前 (i) 个人,第 (i) 个人选出的球来自前一个人/自己,讨论转移。通过钦定第 (1) 个人所选出的球破环求解。复杂度 (mathcal O(n))。(我没实现所以讲得比较糊 www。

    (mathcal{Code})

      只有方法一的代码呢。

    /*-Rainybunny-*/
    
    #include <bits/stdc++.h>
    
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    
    const int MAXN = 1e6, MOD = 998244353, INV2 = 499122177, INV3 = 332748118;
    int n, a[MAXN + 5];
    
    inline int mul( const int u, const int v ) { return 1ll * u * v % MOD; }
    inline int sub( int u, const int v ) { return ( u -= v ) < 0 ? u + MOD : u; }
    inline int add( int u, const int v ) { return ( u += v ) < MOD ? u : u - MOD; }
    
    struct Matrix {
        int a, b, c, d;
        friend inline Matrix operator * ( const Matrix& u, const Matrix& v ) {
            return { add( mul( u.a, v.a ), mul( u.b, v.c ) ),
              add( mul( u.a, v.b ), mul( u.b, v.d ) ),
              add( mul( u.c, v.a ), mul( u.d, v.c ) ),
              add( mul( u.c, v.b ), mul( u.d, v.d ) ) };
        }
    } pre[MAXN + 5], suf[MAXN + 5];
    
    inline Matrix getTrans( const int i, const bool type ) {
        int tmp = mul( mul( a[i], a[i] + 1 ), INV2 );
        if ( !type ) {
            return { tmp, a[i] + 1,
              mul( sub( a[i], mul( add( a[i], a[i] ) + 1, INV3 ) ), tmp ), tmp };
        } else {
            return { sub( mul( a[i], a[i] ), tmp ), a[i],
              mul( sub( a[i], mul( add( a[i], a[i] ) + 1, INV3 ) ), tmp ), tmp };
        }
    }
    
    int main() {
        // freopen( "y.in", "r", stdin );
        // freopen( "y.out", "w", stdout );
        std::ios::sync_with_stdio( false ), std::cin.tie( 0 );
    
        std::cin >> n;
        rep ( i, 1, n ) std::cin >> a[i];
    
        pre[0] = { 1, 0, 0, 1 };
        rep ( i, 1, n ) pre[i] = getTrans( i, 1 ) * pre[i - 1];
        suf[n + 1] = { 1, 0, 0, 1 };
        per ( i, n, 1 ) suf[i] = suf[i + 1] * getTrans( i, 0 );
    
        int ans = 0;
        rep ( i, 1, n ) { // i won't give i+1 any ball.
            Matrix&& tmp( pre[i - 1] * suf[i + 1] );
            ans = add( ans, add( mul( a[i], tmp.a ), tmp.c ) );
        }
        std::cout << ans << '
    ';
        return 0;
    }
    
    
  • 相关阅读:
    Python学习(四十三)—— Djago-admin管理工具
    Python心得基础篇【1】入门篇
    ServletRequest接口和HttpServletRequest接口
    Java swing
    postgresSQL指令
    Oracle数据库相关
    Java 接口
    Java 求一段代码运行所需要的时间——模板方法设计模式
    Java SE基础巩固
    Java开发环境
  • 原文地址:https://www.cnblogs.com/rainybunny/p/15431076.html
Copyright © 2011-2022 走看看