zoukankan      html  css  js  c++  java
  • CF850F Rainbow Balls

    CF850F Rainbow Balls [* interesting]

    (n) 个种颜色的球,第 (i) 个颜色的球有 (a_i) 个。当袋子有至少两个不同颜色的球时,执行以下操作:

    1. 先后随机取出两个球,然后将第二个球涂成第一个球的颜色。(允许同色)

    这些步骤均只需要 (1s),输出无法操作的期望时间。

    答案对 (10^9+7) 取模。

    (nle 2500,a_ile 10^5)

    Solution

    算是比较 trickly 的时停技巧的使用了吧。

    定义 (S_t) 表示时间 (t) 时的局面,定义 (phi(S_t)) 表示时间 (t) 时的局面 (S_t) 的势函数,我们希望选择合适的势函数,使得 (phi(S_{end})) 为一个常数,同时在期望意义下每次操作 (phi) 均会减少 (1),那么这样 (phi(S_{begin})-phi(S_{end})) 就是我们需要求的答案。

    考虑定义 (f(a_i)) 表示颜色 (i)(a_i) 个球的势函数,定义 (F(S)=sum f(a_i)) 以表示局面的势函数,记 (m=sum a_i),那么有:

    1. 我们有 (frac{a_i(a_i-1)}{m(m-1)}) 的概率选中两个 (i) 类球
    2. 我们有 (frac{a_ia_j}{m(m-1)}) 的概率将 (i) 变成 (j)

    于是有:

    [egin{aligned} &phi(S_{t+1})=frac{1}{m(m-1)}igg(sum_i a_i(a_i-1)phi(S_t)+sum_isum_{j e i} a_ia_j(phi(S_t)+f(a_i+1)-f(a_i)+f(a_j-1)-f(a_j))igg) \&=frac{1}{m(m-1)}igg(sum_i Big(a_i(a_i-1)+a_i(m-a_i)Big)phi(S_t)+sum_i a_i(m-a_i)(f(a_i+1)-2f(a_i)+f(a_i-1))igg) \&=frac{1}{m(m-1)}igg(sum_i Big( ma_i-a_iBig)phi(S_t)+sum_i a_i(m-a_i)(f(a_i+1)-2f(a_i)+f(a_i-1))igg) \&=frac{1}{m(m-1)}igg(m(m-1)phi(S_t)+sum_i a_i(m-a_i)(f(a_i+1)-2f(a_i)+f(a_i-1))igg) \&=phi(S_t)+frac{1}{m(m-1)}sum_i a_i(m-a_i)(f(a_i+1)-2f(a_i)+f(a_i-1)) end{aligned}]

    由于我们希望 (phi(S_{t+1})-phi(S_t)=-1),于是有:

    [egin{aligned} &-1=frac{1}{m(m-1)}sum_i a_i(m-a_i)(f(a_i+1)-2f(a_i)+f(a_i-1)) \&0=~m+frac{1}{m-1}sum_i a_i(m-a_i)(f(a_i+1)-2f(a_i)+f(a_i-1)) \&0=sum_i a_iigg(1+frac{m-a_i}{m-1}(f(a_i+1)-2f(a_i)+f(a_i-1))igg) end{aligned}]

    由于我们希望的是更一般的情况,于是这个式子对于任意的 (a_i) 均成立,所以有:

    [1+frac{m-x}{m-1}(f(x+1)+f(x-1)-2f(x))=0 ]

    恒成立。

    故:

    [(f(x+1)+f(x-1)-2f(x))=-frac{m-1}{m-x} ]

    考虑定义 (g(x)=f(x)-f(x-1)),那么 (g(x+1)-g(x)=-frac{m-1}{m-x})

    接着我们认为 (g(0))(f(0)) 均为常数,那么有:

    [g(x)=g(0)+sum_{j=0}^{x-1} frac{1-m}{m-j} ]

    [egin{aligned} &f(x)=f(0)+sum_{j=1}^{x} g(j) \&=f(0)+xcdot g(0)-sum_{j=0}^{x-1}frac{(m-1)(x-j)}{m-j} \&=f(0)+xcdot g(0)-x(m-1)+sum_{j=0}^{x-1}frac{(m-1)(m-j-x+j)}{m-j} \&=f(0)+xcdot g(0)-x(m-1)+(m-1)(m-x)sum_{j=0}^{x-1}frac{1}{m-j} end{aligned}]

    方便起见,规定 (g(0)=m-1,f(0)=0),那么就有:

    [f(m)=0 ]

    [f(x)=(m-1)(m-x)sum_{j=0}^{x-1}frac{1}{m-j} ]

    维护倒数和,递推至 (max a_i) 即可。

    此时,(phi(S_{end})=f(m)=0,phi(S_{begin})=sum f(a_i))

    如果写线性逆元的话,复杂度为 (mathcal O(max a+n))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std ;
    #define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
    #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 re register
    #define int long long
    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 P = 1e9 + 7 ;  
    const int N = 1e5 + 5 ; 
    int fpow(int x, int k) {
    	int ans = 1, base = x ;
    	while(k) {
    		if(k & 1) ans = 1ll * ans * base % P ;
    		base = 1ll * base * base % P, k >>= 1 ;
    	} return ans ;
    }
    int n, m, c, a[N], f[N], inv[N] ;  
    signed main()
    {
    	n = gi() ; f[0] = 0 ; 
    	rep( i, 1, n ) a[i] = gi(), c += a[i], m = max( m, a[i] ) ; 
    	rep( i, 0, m ) inv[i] = fpow(c - i, P - 2) ; 
    	rep( i, 1, m ) inv[i] = (inv[i - 1] + inv[i]) % P ; 
    	rep( i, 1, m ) f[i] = (c - 1) * (c - i) % P * inv[i - 1] % P ; 
    	int ans = 0 ;
    	rep( i, 1, n ) ans = (ans + f[a[i]]) % P ; 
    	cout << ans % P << endl ; 
    	return 0 ;
    }
    
  • 相关阅读:
    ASP.NET MVC 3 学习笔记系列之Music Store(1)
    sql 拆分 逗号 函数
    软件开发项目的人力资源管理 团队配置问题探讨
    从某失败项目中学到的经验教训
    需求为王
    信息系统项目管理师考试经验分享
    JSP中文乱码问题及编码知识详解
    详解java中instanceof各种的用法
    mvc开源项目
    asp.net服务组件自动事务处理
  • 原文地址:https://www.cnblogs.com/Soulist/p/13906776.html
Copyright © 2011-2022 走看看