• [CF1439D] INOI Final Contests


    [题目链接]

    https://codeforces.com/contest/1439/problem/D

    [题解]

    首先解决 (N = M) 的情况。

    不妨设 (dp1_{i}) 表示 (i) 个人 (i) 个座位的合法方案数 , 枚举最后一个人坐的位置。 由于左右两侧独立 , 得到

    (dp1_{i}=sumlimits_{j=1}^i [j+(i-j+1)]{i-1choose j-1}dp1_{j-1}dp1_{i-j})

    (dp2_{i}) 表示 (i) 个人 (i) 个座位 , 所有情况的移动距离之和。 枚举最后一人的座位 , 单独考虑其贡献 , 得到

    (dp2_{i}=sumlimits_{j=1}^i ({jchoose 2}+{i-jchoose 2}){i-1choose j-1}dp1_{j-1}dp1_{i-j}+[j+(i-j+1)]{i-1choose j-1}(dp2_{j-1}dp1_{i-j}+dp2_{i-j}dp1_{j-1}))

    接着 , 考虑 (N > M) 的情况。

    (dp3_{i , j}) 表示前 (i) 个人 , (j) 个座位被占用的方案数 , 枚举末尾极长一段被连续占用的座位 , 得到

    (dp3_{i,j}=dp3_{i-1,j}+sumlimits_{l=1}^j {jchoose l}dp3_{i-l-1,j-l}cdot dp1_{l})

    类似地 , 令 (dp_{i , j}) 表示前 (i) 个人 , (j) 个座位被占用的移动距离和 , 易知

    (dp4_{i,j}=dp4_{i-1,j}+sumlimits_{l=1}^j {jchoose l}(dp4_{i-1-l,j-l}cdot dp1_{l}+dp3_{i-1-l,j-l}dp2_l))

    这个做法的时间复杂度 (O(NM))。 事实上可以通过多项式做法优化至 (O(NlogN))

    [代码]

    #include<bits/stdc++.h>
     
    using namespace std;
     
    typedef long long LL;
     
    #define rep(i , l , r) for (int i = (l); i < (r); ++i)
     
    const int MN = 505;
     
    int N , M , mod , dp1[MN] , dp2[MN] , dp3[MN][MN] , dp4[MN][MN] , C[MN][MN];
     
    inline void inc(int &x , int y) {
    	x = x + y < mod ? x + y : x + y - mod; 
    }
     
    int main() {
    	 
    	 scanf("%d%d%d" , &N , &M , &mod);
    	 for (int i = 0; i <= 500; ++i) {
    	 	 C[i][0] = C[i][i] = 1;
    	 	 for (int j = 1; j < i; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
    	 }
    	 dp1[0] = 1;
    	 for (int i = 1; i <= 500; ++i) {
    	 	for (int j = 1; j <= i; ++j)
    	 	    inc(dp1[i] , 1ll * dp1[j - 1] * dp1[i - j] % mod * C[i - 1][j - 1] % mod);
    	 	dp1[i] = 1ll * dp1[i] * (i + 1) % mod;
    	 	for (int j = 1; j <= i; ++j) {
    	 		inc(dp2[i] , 1ll * (i + 1) * C[i - 1][j - 1] % mod * (1LL * dp1[j - 1] * dp2[i - j] % mod + 1LL * dp2[j - 1] * dp1[i - j] % mod) % mod);
    			inc(dp2[i] , 1ll * C[i - 1][j - 1] * dp1[j - 1] % mod * dp1[i - j] % mod * (j * (j - 1) / 2 + (i - j) * (i - j + 1) / 2) % mod); 	
    		}
    	 }
    	 dp3[0][0] = 1;
    	 for (int n = 1; n <= 500; ++n) {
    	 	 for (int m = 0; m < n; ++m) {
    	 	 	dp3[n][m] = dp3[n - 1][m];
    			dp4[n][m] = dp4[n - 1][m];
    			for (int i = 1; i <= m; ++i) {
    				inc(dp3[n][m] , 1ll * dp3[n - i - 1][m - i] * dp1[i] % mod * C[m][i] % mod);
    				inc(dp4[n][m] , 1ll * dp3[n - i - 1][m - i] * dp2[i] % mod * C[m][i] % mod);
    				inc(dp4[n][m] , 1ll * dp4[n - i - 1][m - i] * dp1[i] % mod * C[m][i] % mod);
    			}	 
    		 }
    		 dp3[n][n] = dp1[n] , dp4[n][n] = dp2[n];
    	 }
    	 printf("%d
    " , dp4[N][M]);
         return 0;
    }
    
  • 相关阅读:
    微信公众号开发(二)用户关注
    搭建git服务器
    微信公众号开发(三)生成带参数的二维码
    windows 安装多个mysql
    微信公众号开发(一)前期 配置
    支付宝接口之条码支付
    mysql8.0 安装 修改密码 允许远程连接
    区块链开发金融交易平台
    区块链开发 在金融融资交易平台中的优势
    2019年区块链金融交易所钱包开发需要多少钱
  • 原文地址:https://www.cnblogs.com/evenbao/p/14438718.html
Copyright © 2020-2023  润新知