码迷,mamicode.com
首页 > 其他好文 > 详细

AGC007 - C Pushing Ball

时间:2017-12-01 16:41:37      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:其他   特殊   因此   down   getch   i+1   ref   题目   namespace   

Description

题目链接 懒得写详细题意了, 放个链接

\(n\le 2*10^5\) 个球, \(n+1\) 个坑, 排成数轴, 球坑交替. 相邻球-坑距离为等差数列 \(d\). 给定首项与公差. 每次随机选一个球并随机往一个方向推, 求期望经过距离总和

Solution

手玩观察一下, 球不可能没坑掉, 每次推完一个球后变成 \(n-1\) 个球的子问题.

对于每一个子问题, 只考虑推第一个球的期望距离 (\(\frac{\sum_{i=1}^{2n}d_i}{2n}\)) , 其他的在子问题中处理.

考虑对于任意一个子问题, 假设有 \(n\) 个球, 则有 \(2n\) 个子状态, 每个子状态的概率 \(\frac 1{2n}\)

子状态中 \(d‘\) 可根据当前问题的 \(d\) 经过线性运算得出, 推第一个球的期望距离也可由 \(d\) 线性运算得出.

因此, 我们可以将这 \(2n\) 个子问题合并, 合并的子问题中 \(d‘‘_i = E[d‘_i]\). 下面观察 \(d‘‘\) :

下面的图中, 记o为球, d为当前子问题的(期望)每段段长, _为坑, 新d‘‘是从左往右标号的.
   o     o     o     o     考虑每种球掉落方案, 边界球往边界坑掉 是 特殊情况, 其余:
 d1 d2 d3 d4 d5 d6 d7 d8   将相邻的三个d加在一起合成一段, 其他不变. 记段为(l,r)
_     _     _     _     _  那么l=1..2n-2, 考虑每个di (1<=i<=n) 的贡献

\(l\le i-2\) 时, \(d_i\to d‘‘_{i-2}\). \(l=i-1\) 时, \(d_i\to d‘‘_{i-1}\). \(l\ge i\) 时, \(d_i\to d‘‘_{i}\) , 总的来看就是

\(d‘‘_i = d_i+d_{i+2}+i*d_{i+2}+d_{i+1}+(2n-2-i+1)*d_i=(2n-i)d_i+d_{i+1}+(i+1)d_{i+2}\)

\(=(2n+2)d_0+3\Delta + (2n+4)i\Delta\) , 于是原问题等差, 合并后子问题等差, \(\cdots\), 都等差.

实现很简单

Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
#define rep(i, a, b) for (int i = (a), _ = (b); i <= _; ++ i)
#define per(i, a, b) for (int i = (a), _ = (b); i >= _; -- i)
#define For(i, a, b) for (int i = (a), _ = (b); i < _; ++ i)
#define ri rd<int>
typedef long double db;
using namespace std;

template<class T> inline T rd() {
    bool f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = 0;
    T x = 0; for (; isdigit(c); c = getchar()) x = x * 10 + c - 48; return f ? x : -x;
}

int n;
db d0, delta, ans;

inline db calc(db d0, db delta, db len) {
    return len * d0 + delta * len * (len + 1) / 2;
}

int main() {
    
    n = ri(), d0 = ri(), delta = ri(), d0 -= delta;
    per (i, n, 1) {
        ans += calc(d0, delta, 2 * i) / (2 * i);
        d0 = (2 * i + 2) * d0 + 3 * delta;
        delta *= (2 * i + 4);
        d0 /= 2 * i;
        delta /= 2 * i;
    }

    printf("%.15Lf\n", ans);

    return 0;
}

AGC007 - C Pushing Ball

标签:其他   特殊   因此   down   getch   i+1   ref   题目   namespace   

原文地址:http://www.cnblogs.com/acha/p/7942778.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!