小S在一个\(n\times n\)的棋盘上玩游戏。
他首先在每个方格上随机地填入\(1\)到\(m\)之间的正整数(每个方格填的数互不相同),然后随机地选出k个数字(可能不在棋盘上),把它们出现在棋盘上的方格涂黑。
设有R行被整行涂黑,有C列被整列涂黑,便可以得到\(2^{R+C}\)分。
求他的期望得分。
输入格式
第一行三个整数\(n,m,k\)。
输出格式
仅一行包含一个实数,为期望得分。如果答案\(\ge10^{99}\)就输出\(10^{99}\),输出被认为正确当且仅当你的输出与标准输出的相对误差不超过\(10^{−6}\)。
样例
样例一
input
1 2 1
output
2.5
约定与限制
对于30% 的数据,满足 \(2≤n≤5,m≤10\)。
对于60% 的数据,满足 \(2≤n≤10,m≤200\)。
对于100% 的数据 ,满足$ 2≤n≤300,2≤m≤100000,n≤k≤m$ 。
时间限制:1s
空间限制:512MB
这道题首先有个误区:假设涂满了\(2\)行\(1\)列,同时我们也涂满了\(1\)行\(1\)列,也要加上\(2^{1+1}=4\)。
我们枚举涂了几行几列,设枚举到涂了\(i\)行\(j\)列。期望等于概率乘分数,分数是\(2^{i+j}\),概率首先我们要保证有\(i\)行\(j\)列,所以选中某\(i\)行某\(j\)列的概率为\(C^i_n/2^i\times C^j_n/2^j\),一乘就和分数抵消了,但是我们还要在所有格子中填满指定的\(i\)行\(j\)列。填满这些格子总共需要填\(i\times n+j\times(n-i)\)个。总而言之,我们要预处理出\(C_n^i\)和填满指定\(i\)个格子的概率。
\(C^i_n\)的预处理方法很经典.设\(c_i=C_n^i\)按照组合数的的基本计算方法,\(C_n^i=\dfrac{n!\div(n-i)!}{i!}\),那么\(c_i=c_{i-1}\times(n-i+1)\div i\).
到了更复杂的填满\(i\)个格子的概率了。每多要求一个格子,都有\(\dfrac{k-i+1}{m-i+1}\)的几率选中。设选\(i\)个格子概率为\(p_i\),那么\(p_i=p_{i-1}\times(k-i+1)\div (m-i+1)\)
最后计算就可以了
#include<cstdio>
const int N=305;
int n,m,k,s;
double p[N*N],c[N],ans;
int main()
{
scanf("%d%d%d",&n,&m,&k);
c[0]=p[0]=1;
for(int i=1;i<=n;i++)
c[i]=c[i-1]*(n-i+1)/i;
for(int i=1;i<=k;i++)
p[i]=p[i-1]*(k-i+1)/(m-i+1);
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
s=i*n+(n-i)*j;
if(s<=k)
ans+=c[i]*c[j]*p[s];
}
}
if(ans>1e99)
printf("%lf",1e99);
else
printf("%lf",ans);
return 0;
}
标签:,10,填满,概率,格子,int,times 来源: https://www.cnblogs.com/mekoszc/p/16148509.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。