【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; }