【bzoj2134】单选错位

题目描述

有n道题,第i道题有ai个选项。把第i道题的正确答案填到第i+1道题上(n填到1),问期望做对几道题。


输入

n很大,为了避免读入耗时太多,
输入文件只有5个整数参数n, A, B, C, a1,
由上交的程序产生数列a。
下面给出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的含义见题目描述。
 2≤n≤10000000, 0≤A,B,C,a1≤100000000


输出

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


样例输入

3 2 0 4 1


样例输出

1.167

 



题解

因此每道题对的期望都是独立的,根据排列分析,对于每道题都有 a[ i-1 ] 种选择和 a[ i ] 种选项,那么一共就有 a[ i-1 ] * a[ i ] 种排列,其中只有 min ( a[ i-1 ] , a[ i ] ) 种是正确的。

所以  dp[ i ] = min( a[ i-1 ] , a[ i ] ) / a[ i ] * a[ i -1 ] =  1 /  max( a[ i ] , a[ i -1 ] ) 。

 

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxn=10000000+5;

int n,A,B,C,a1,a[maxn];
double ans;

int main(){
    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; 
    for(int i=2;i<=n;i++) ans+=1.0/max(a[i-1],a[i]);
    ans+=1.0/max(a[n],a[1]);
    printf("%.3lf\n",ans);
    return 0;
}

 

posted @ 2018-08-18 08:17  rld  阅读(93)  评论(0编辑  收藏  举报