1 条题解

  • 0
    @ 2026-6-24 11:41:52
    • [AT5300 原题链接]\color{lightgreen}\text{[AT5300 原题链接]}

    • 题目描述
      给出 N 个骰子, 同时投掷 K 个连续骰子, 要求出可能的最大数学期望值。

    • 输入格式
      第一行两个数, NK . 第二行 N 个数, 代表每一个骰子的面数。

    • 输出格式
      一个 12 位的小数, 表示最大数学期望值。

    • 思路
      首先, 我们要先知道, 数学期望值是什么?

      数学期望值是试验中每次可能的结果乘以其结果概率的总和。

      也就是说在骰子里的数学期望值就是它的所有面的点数之和除以它的面数。 我们假设这是一个有 n 面的骰子, 那么它的数学期望值就是:

      1+2+3+...+(n2)+(n1)+nn\frac{1+2+3+...+(n-2)+(n-1)+n}{n}

      根据我们的观察, 可以发现, (1+2+3+...+(n2)+(n1)+n)(1+2+3+...+(n-2)+(n-1)+n) 是一个等差数列求和的式子。

      我们知道, 等差数列求和公式是 (1+n)n2\frac{(1+n)n}{2} .

      所以, 把上面的式子化简一下就成了这样:

      (1+n)n2n\frac{\frac{(1+n)n}{2}}{n}

      我们再把 n 约分掉, 最终就成了这样:

      1+n2\frac{1+n}{2}

      知道了这个式子, 那这题就简单了。

      因为是连续的骰子, 所以我们只需要用一个前缀和数组把答案存起来就行了, 最后在用 for 循环和前缀差求出最大值就行了。

    • 代码实现

    #include <bits/stdc++.h>
    #define N 200001
    #define int long long
    using namespace std;
    int n, k;
    double prefix[N], p[N], maxn;
    signed main() {
    	cin >> n >> k;
    	for(int i = 1; i <= n; i++) {
    		cin >> p[i];
    		p[i] = (1 + p[i]) / 2;
    		prefix[i] = prefix[i - 1] + p[i];
    	}
    	for(int i = k; i <= n; i++) {
    		maxn = max(maxn, prefix[i] - prefix[i - k]);
    	}
    	printf("%0.12lf\n", maxn);
    	return 0;
    }
    
    • 此题解仅供参考, 谢谢 !
    • 1

    信息

    ID
    11821
    时间
    2000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    2
    已通过
    2
    上传者