嘘~ 正在从服务器偷取页面 . . .

洛谷P1297 [国家集训队]单选错位 题解


洛谷P1297 [国家集训队]单选错位 题解

题目链接:P1297 [国家集训队]单选错位

题意

gx 和 lc 去参加 noip 初赛,其中有一种题型叫单项选择题,顾名思义,只有一个选项是正确答案。

试卷上共有 \(n\) 道单选题,第 \(i\) 道单选题有 \(a_i\) 个选项,这 \(a_i\) 个选项编号是 \(1,2,3,\ldots,a_i\),每个选项成为正确答案的概率都是相等的。

lc 采取的策略是每道题目随机写上 \(1 \sim a_i\) 的某个数作为答案选项,他用不了多少时间就能期望做对 \(\sum_{i=1}^n \frac{1}{a_i}\) 道题目。gx 则是认认真真地做完了这 \(n\) 道题目,可是等他做完的时候时间也所剩无几了,于是他匆忙地把答案抄到答题纸上,没想到抄错位了:第 \(i\) 道题目的答案抄到了答题纸上的第 \(i+1\) 道题目的位置上,特别地,第 \(n\) 道题目的答案抄到了第 \(1\) 道题目的位置上。

现在 gx 已经走出考场没法改了,不过他还是想知道自己期望能做对几道题目,这样他就知道会不会被 lc 鄙视了。

我们假设 gx 没有做错任何题目,只是答案抄错位置了。

输入格式

\(n\) 很大,为了避免读入耗时太多,输入文件只有 \(5\) 个整数参数 \(n, A, B, C, a_1\),由上交的程序产生数列 \(a\)。下面给出 C/C++ 的读入语句和产生序列的语句(默认从标准输入读入):

// for C/C++
scanf("%d%d%d%d%d", &n, &A, &B, &C, a + 1);
for (int i = 2; i <= n; i++)
	a[i] = ((long long) a[i - 1] * A + B) % 100000001;
for (int i = 1; i <= n; i++)
	a[i] = a[i] % C + 1;

选手可以通过以上的程序语句得到 \(n\) 和数列 \(a\)\(a\) 的元素类型是 \(32\) 位整数),\(n\)\(a\) 的含义见题目描述。

输出格式

输出一个实数,表示 gx 期望做对的题目个数,保留三位小数。

对于 \(100\%\) 的数据,\(2\leq n\leq 10^7, 0\leq A,B,C \leq 10^8\)\(1 \leq a_i \leq 10^8\)

简单的概率题。稍微分讨一下就好了。

  • \(a_i = a_{i+1}\) 时,期望为 \(\frac{1}{a_i} = \frac{1}{a_{i+1}}\)
  • \(a_i > a_{i+1}\) 时,期望为 \(\frac{a_{i+1}}{a_i}\times\frac{1}{a_{i+1}} = \frac{1}{a_i}\)
  • \(a_i < a_{i+1}\) 是,期望为 \(\frac{a_i}{a_{i+1}} \times \frac{1}{a_i}=\frac{1}{a_{i+1}}\)

所以答案其实就是 \(\sum \frac{1}{\max\{a_{i},a_{i+1}\}}\)

时间复杂度 \(\mathcal{O}(n)\)

代码:

#include <bits/stdc++.h>
using namespace std;
// #define int long long
// #define INF 0x3f3f3f3f3f3f3f3f
typedef long long ll;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e7+15))

double res; int n,A,B,C,a[N];
void gen()
{
    cin >> n >> A >> B >> C >> a[1];
    for(int i=2; i<=n; i++)
        a[i] = ((ll)a[i - 1] * A + B) % 100000001;
    for(int i=1; i<=n; i++) a[i] = a[i] % C + 1;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cout << fixed << setprecision(3);
    gen(); res = 1.0 / (max(a[1], a[n]));
    for(int i=2; i<=n; i++)
        res += 1.0 / (max(a[i], a[i-1]));
    cout << res << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录