zoukankan      html  css  js  c++  java
  • CF1267G

    CF1267G

    很有意思的题。

    给定 (n) 张卡,第 (i) 张的价格为 (c_i)

    你有两种方式获得卡牌:

    • 随机抽一张卡,花费为 (x),如果得到了一个已经有的卡,那么返还 (frac{x}{2})
    • 直接购买一张卡,花费为 (c_i)

    求期望花多少集齐所有卡。

    精度要求 (10^{-9})

    (nle 100,sum c_ile 10^4)


    Solution

    注意到决策一定是先抽卡,然后再全买。

    那么我们可以改变决策的方式,变成选择一种方式获得卡:

    • 按照规则随机抽卡。
    • 随机抽一张没有的卡并获得,花费为这张卡的花费。

    我们发现这种情况下的最优解和原问题等价。

    同时,由于每次抽卡均为随机抽卡,所以假设我们抽了 (i) 张不同的卡出来,那么这 (i) 张卡也将是随机的卡,换而言之原集中每种大小为 (i) 的子集被抽出的概率均相同!

    现在考虑我们有 (i) 张卡,期望花费多少得到 (i+1) 张卡,不难发现期望花费为:((frac{n}{n-i}+1) imes frac{x}{2}),前面表示期望抽的次数,(+1) 表示最后一次抽会额外附带 (frac{x}{2}) 的贡献。

    修改规则后,我们发生如果剩余的权值和为 (c),当前剩余 (k) 个元素,那么问题等价于期望以 (frac{c}{k}) 的贡献得到一个元素,否则以 ((frac{n}{k}+1) imes frac{x}{2}) 的贡献得到一个元素。

    于是我们只需要比对这两者的大小,如果 (frac{c}{k}) 更大,那么以其期望产生贡献,否则以 ((frac{n}{k}+1) imes frac{x}{2}) 产生贡献。

    将每一种情况发生的概率乘以贡献求和即为答案。

    注意到所有子集的等价性,保留 (k) 个数使得权值和为 (c) 的概率是可以算出来的,于是这个题就做完了,复杂度 (mathcal O(n^2sum c))

    • 其实就是为了保证精度,边算边除以 (frac{1}{inom{n}{k}})(inom{n}{k}leftarrow inom{n}{k-1} imes frac{n-k+1}{k})

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
    #define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
    #define D long double
    int gi() {
    	char cc = getchar() ; int cn = 0, flus = 1 ;
    	while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    	while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    	return cn * flus ;
    }
    const int N = 100 + 5 ; 
    int n, c[N], m ;
    D ans, t, f[N][10005] ; 
    D Min(D x, D y) { return min(x, y) ; }
    signed main()
    {
    	n = gi(), t = gi(), t /= 2.0 ; 
    	rep( i, 1, n ) c[i] = gi(), m += c[i] ; f[0][0] = 1 ; 
    	rep( i, 1, n ) drep( k, 1, i ) rep( j, c[i], m ) 
    	f[k][j] = (f[k][j] + f[k - 1][j - c[i]] * k / (1.0 * (n - k + 1)) ) ;
    	rep( k, 1, n ) rep( j, 0, m ) 
    		ans = (ans + f[k][j] * Min( ((D)n / (D)k + 1) * t, (D)j / ((D)k)) ) ; 
    	printf("%.10Lf
    ", ans ) ; 
    	return 0 ;
    }
    
  • 相关阅读:
    测试某个方法的执行时间
    DataTable与DataGridView绑定
    《认知与设计——理解UI设计准则》笔记(7) 我们的注意力有限,记忆力也不完美
    常用软件收集
    通过反射得到某个实体的属性值
    获取某个字段的最大值
    C# ServerVariables参数说明
    C# 将网址转换为16进制可用网址,防盗链,%%
    不加修改权限的前提,要分辨出那些图片是删除不用的
    C# Winform 域名得到(查询)(服务器所在) IP  cs
  • 原文地址:https://www.cnblogs.com/Soulist/p/13713365.html
Copyright © 2011-2022 走看看