您的位置:首页 > 其它

noip模拟小象涂色

2015-09-24 22:09 288 查看
小象涂色

题目描述:

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

输入描述:

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

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

接下来k行,每行两个整数Li,Ri,表示第i个操作的L和R。

输出描述:

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

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

好吧,开始说怎么做。

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

最容易想到的dp是f[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<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
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<maxc;i++)
for(int j=0;j<c;j++)
{
f[i+1][j]+=f[i][j]/2;
for(int k=0;k<c;k++)
f[i+1][(j*k)%c]+=f[i][j]/(2*c);
}
ans=0;
for(int i=1;i<=n;i++)
for(int j=0;j<c;j++)
ans+=f[cs[i]][j]*j;
printf("%.9f\n",ans);
}
int main()
{
scanf("%d",&T);
while(T--)
{init();dp();}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: