zoukankan      html  css  js  c++  java
  • 【SSL 1481】 最大前缀和

    题目大意:

    一段长 (n+m) 的序列,其中 (n) 个是 1,(m) 个是 0。对序列排列求它所有前缀和的最大值的和。

    正文:

    如图,其实我们就是要从点 ((0,0)) 到点 ((n+m,n-m))(x) 轴为走的步数,(y) 轴为最大前缀和。假设我们强制到 (y) 轴的 (y_2),设 (y_1) 为终点即 (n-m)

    经过 (y_2) 的总方案为 (C_{n+m}^{(n+m)-(y_2-y_1)}),运用前缀和思想,那只经过 (y_2) 不经过 (y_2+1) 的方案数就是(y_2 + 1) 的减去 (y_2) 的。

    代码:

    ll pow(ll a, int b)
    {
        a %= p;
    	ll ans = 1;
    	for(; b; b >>= 1, a = a * a % p)
    		if(b & 1)
    			ans = ans * a % p;
        return ans;
    }
    
    inline void _init(int n, int m)
    {
    	prod[0] = inv[1] = 1;
    	for (register int i = 1; i <= m; i++)
    		prod[i] = (prod[i - 1] * i) % p;
    	inv[n + m] = pow(prod[n + m], p - 2);
    	for (register int i = n + m - 1; i > 1; --i)
    		inv[i] = inv[i + 1] * (i + 1) % p;
    }
    
    inline ll C(ll n,ll m){
        if(m > n)return 0;
        return (prod[n]*inv[m] % p * inv[n - m] % p);
    }
    
    int main()
    {
    	scanf ("%lld%lld", &n, &m);
    	_init(0, n + m);
    	ll pre = 1;
    	ans = n;
    	for (register int i = n - 1; i >= n - m; --i)
    	{
    		ll s = (C(n + m, (n - i) % p) - pre + p) % p;
    		pre = (s + pre) % p;
    		if(i > 0) ans = (ans + s * i % p) % p;
    		else break;
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    浅谈Java中的equals和==与hashCode
    数组操作
    python-类
    javascript操控浏览器
    javascript_获取浏览器属性
    javascript_data
    python3_phantomJS_test
    python检测字符串的字母
    python百分比数比较大小
    selenium加载时间过长
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/13507417.html
Copyright © 2011-2022 走看看