zoukankan      html  css  js  c++  java
  • 2018 ACM-ICPC World Finals Problem D. Gem Island(递推)

    2018 ACM-ICPC World Finals Problem D. Gem Island

    题目大意

    • n n n个人,初始每个人手上有一颗宝石,每天等概率有一颗宝石变为两颗,求 d d d天后宝石数最多的 r r r个人的期望宝石总数。
    • 1 ≤ n , d ≤ 500 1le n,dle500 1n,d500 1 ≤ r ≤ n 1le rle n 1rn

    题解

    • 首先通过手玩样例可以发现,最终的每种状态出现的次数都是相等的,均为 d ! d! d!次,不同的操作方案有 n ∗ ( n + 1 ) ∗ . . . ∗ ( n + d − 1 ) n*(n+1)*...*(n+d-1) n(n+1)...(n+d1) ( n + d − 1 ) ! ( n − 1 ) ! frac{(n+d-1)!}{(n-1)!} (n1)!(n+d1)!种,那么考虑先求出各种不同的最终状态,再乘上和除去相应的数。
    • 则相当于求和为 n + d n+d n+d n n n个数,且保证每个数至少为 1 1 1的所有方案的前 r r r个数之和。
    • 不难想到可以设状态递推,按照很普通的设法,设 f i , j f_{i,j} fi,j表示到第 i i i个人,此时前 i i i个数和为 j j j的答案,每次枚举第 i i i个人的数来转移,但是发现这样并不能统计“前 r r r大”这一条件。如果多设一维的话,复杂度无法满足要求。
    • 不妨换一个角度,考虑起初每个人都是 1 1 1个共 n n n个,然后选 s 1 s1 s1人变成 2 2 2个,总数变成 n + s 1 n+s1 n+s1个,方案数乘上 ( n s 1 ) nchoose s1 (s1n);接着在 s 1 s1 s1人中选 s 2 s2 s2人变成 3 3 3个,总数变成 n + s 1 + s 2 n+s1+s2 n+s1+s2个,方案数乘上 ( s 1 s 2 ) s1choose s2 (s2s1),以此类推。
    • 这样子可以少去记录第几个人的状态,而可以用来记录上一次加入了多少人,每次对最终前 r r r大的贡献为 m i n ( r , s x ) min(r,s_x) min(r,sx) s x s_x sx为当前加入的个数。

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ld long double
    #define N 510
    ld f[N * 2][N], g[N * 2][N], c[N][N];
    int main() {
    	int n, d, r, i, j, k;
    	scanf("%d%d%d", &n, &d, &r);
    	for(i = 0; i <= n; i++) {
    		c[i][0] = c[i][i] = 1;
    		for(j = 1; j < i; j++) c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
    	}
    	f[n][n] = r, g[n][n] = 1;
    	for(i = n; i < n + d; i++) {
    		for(j = 1; j <= n; j++) if(g[i][j]) {
    			for(k = 1; k <= j && i + k <= n + d; k++) {
    				g[i + k][k] += g[i][j] * c[j][k];
    				f[i + k][k] += f[i][j] * c[j][k] + g[i][j] * c[j][k] * min(k, r);
    			}
    		}
    	}
    	ld s = 0;
    	for(i = 1; i <= n; i++) s += f[n + d][i];
    	for(i = n; i <= n + d - 1; i++) s /= i; 
    	for(i = d; i; i--) s *= i;
    	printf("%.10LF", s);
    	return 0;
    }
    

    自我小结

    • 注意方案数和贡献同时转移的递推中,贡献转移需要乘上转移的方案数。
    • 程序修改时要注意原数组的大小是否适合新做法,要检查极限数据情况下的数组是否越界。
    哈哈哈哈哈哈哈哈哈哈
  • 相关阅读:
    js数组直接赋值会导致一个数组改变,另一个数组会随之改变(解决办法)
    css兼容性问题
    12种CSS BUG解决方法与技巧
    js的运算小数点的问题
    DataTable相关操作,筛选,取前N条数据,去重复行,获取指定列数据
    js得到区域长宽
    DataView.RowFilter筛选DataTable中的数据
    图片加载问题
    kissy延迟加载demo
    解决css兼容性
  • 原文地址:https://www.cnblogs.com/LZA119/p/14608426.html
Copyright © 2011-2022 走看看