[CSP-S模拟测试]:大佬(kat)(数学期望)

题目描述

辣鸡$ljh\ NOI$之后就退役了,然后就滚去学文化课了。
他发现$katarina$大佬真是太强了,于是就学习了一下$katarina$大佬的做题方法。
比如这是一本有$n$道题的练习册,$katarina$大佬每天都会做k道题。
第一天做第$1~k$题,第二天做第$2~k+1$题……第$n-k+1$天做第$n-k+1~n$道题。
但是辣鸡$ljh$又不想太累,所以他想知道$katarina$大佬做完这本练习册的劳累度。
每道题有它的难度值,假设今天$katarina$大佬做的题目中最大难度为$t$,那么今天$katarina$大佬的劳累度就是$w_{t_i}$,做完这本书的劳累值就是每天的劳累值之和。
但是辣鸡$ljh$一道题都不会,自然也不知道题目有多难,他只知道题目的难度一定在$1~m$之间随机。
他想让即将参加$NOIP$的你帮他算算$katarina$大佬做完这本书的劳累值期望。


输入格式

第一行,三个整数$n,m,k$。
第二行,$m$个整数表示$w_{t_1},,,,w_{t_m}$。


输出格式

输出劳累值期望对1000000007取模的值。


样例

样例输入1:

2 2 2
1 2

样例输出1:

750000007

样例输入2:

5 4 3
2 1 3 5

样例输出2:

890625018


数据范围与提示

样例1解释:

有${1,1},{1,2},{2,1},{2,2}$四种可能,期望为$\frac{7}{4}$。

数据范围:

$n\leqslant 500$。

$m\leqslant 400$。


题解

又是一道假期望……

注意这句话:第一天做第$1~k$题,第二天做第$2~k+1$题……第$n-k+1$天做第$n-k+1~n$道题。

而不是:第一天做第$1~k$题,第二天做第$k+1~2\times k$题……第$\frac{n}{k}$天做第$n-k+1~n$道题。

一看就是道概率$DP$,那么考虑怎么定义$DP$式子。

定义$dp[i][j]$表示已经做了$i$道题且最大难度小于等于$j$的劳累值期望。

考虑如何进行状态转移,分两种情况:

  $\alpha.$当最大值小于$j$时,显然可以直接转移,即:$dp[i][j]=dp[i][j-1]$。

  $\beta.$当最大值等于$j$时,枚举最大值第一次出现的位置:

    $dp[i][j]+=\sum \limits_{l=1}^{i}dp[l-1][j]\times m^{i-l}+j\times k\times m^{i-1}+dp[i-1][j]\times m^{l-1}$

注意边界情况即可。

还需要注意的一点是,如果k<n则无解,特判一下就好啦~

时间复杂度:$\Theta(n^2m)$。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
long long ans;
long long w,t,l;
long long qpow(long long x,long long y)
{
	long long res=1;
	while(y)
	{
		if(y&1)res=(res*x)%1000000007;
		x=(x*x)%1000000007;
		y>>=1;
	}
	return res;
}
int main()
{
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld",&w);
		t=qpow(i,k);
		ans=(ans+(t-l+1000000007)*w%1000000007)%1000000007;
		l=t;
	}
	long long inv=qpow(qpow(m,k),1000000005);
	cout<<max((n-k+1),0)*ans%1000000007*inv%1000000007<<endl;
	return 0;
}

rp++

posted @ 2019-07-31 14:16  HEOI-动动  阅读(383)  评论(0编辑  收藏  举报