noip模拟小象涂色

小象涂色

题目描述:

小象喜欢为箱子涂色。小象现在有c种颜色,编号为0~c-1;还有n个箱子,编号为1~n,最开始每个箱子的颜色为1。小象涂色时喜欢遵循灵感:它将箱子按编号排成一排,每次涂色时,它随机选择[LR]这个区间里的一些箱子(不选看做选0个),为之涂上随机一种颜色。若一个颜色为a的箱子被涂上b色,那么这个箱子的颜色会变成(a*bmod c。请问在k次涂色后,所有箱子颜色的编号和期望为多少?

输入描述:

第一行为T,表示有T组测试数据。

对于每组数据,第一行为三个整数n,c,k

接下来k行,每行两个整数LiRi,表示第i个操作的LR

输出描述:

对于每组测试数据,输出所有箱子颜色编号和的期望值,结果保留9位小数。

这是一道概率题,没有看题解前,我一如既往地看不懂题意,算不出测试样例。。。

好吧,开始说怎么做。

首先注意随机选择一段区间(有可能为0),表明每个箱子每次被染色的概率为1/2

最容易想到的dpf[i][j][k]表示第i个箱子第j次染色,染为k颜色的概率。明显时间复杂度过高,只能拿部分分。

再仔细观察就会发现,对于每个箱子,它们的本质是相同的,也就是第几个箱子这一维状态是不需要存在的。所以dp状态可简化为f[i][j],表示操作i次,颜色变为j的概率。

读入时统计每个箱子操作的次数cs[i],初始化f[0][1]=1;

F[i+1][j]+=f[i][j]/2;

F[i+1][(j+k)%c]+=f[i][j]/(2*c);

最后的答案就可以表示为∑f[cs[i]][j]*j。

贴代码:

#include
#include
#include
#include
using namespace std;
int T,n,c,K,cs[55],maxc;
double f[55][110],ans; 
void init()
{
	scanf("%d%d%d",&n,&c,&K);
	memset(cs,0,sizeof(cs));
	maxc=0;
	int x,y;
	for(int i=1;i<=K;i++)
	{
		scanf("%d%d",&x,&y);
		for(int j=x;j<=y;j++)
		{
			cs[j]++;
			maxc=max(maxc,cs[j]);
		}
	}
}
void dp()
{
	//一个物品操作i次,颜色变为j的概率。
	//每个箱子的本质是相同的。 
	memset(f,0,sizeof(f));
	f[0][1]=1;
	for(int i=0;i


你可能感兴趣的:(数学期望,动态规划)