lightoj 1284 Grid

来源:互联网 发布:luajit for windows 编辑:程序博客网 时间:2024/05/10 03:27

概率题:lightoj1284

最经典的想法:计算各个点的概率,由于概率满足相加原理,所以求和即可


这个题的数据范围看上去是很大的,x,y,z都是100,k是10000

所以两种可能:

枚举坐标x,y,z,数据规模到100*100*100

枚举k,最大能到O(nlogn),也就是10000*log(10000)

才能够保证不超时


必须选择枚举坐标:原因是概率题,计算每个坐标的符合条件的可能性,再求和

那么思考:坐标(i,j,k)什么时候会被选中?

根据题意,必须i在(i1,i2)之间,j在(j1,j2)之间,k在(k1,k2)之间,该点才会被选中

这是k=1的情况

如果k=3可以吗?k=5可以吗?所以,奇数次方都是满足条件的

那么,对于给定的坐标,k=1时,取的概率是可以求的

根据乘法原理:点在区间内=横坐标在x的区间内*纵坐标在y的区间内*竖坐标在z的区间内

在区间内的计算方法=所有情况-不在区间内的情况(也就是两侧)

所以有了calc函数求得p


然后,如何求得各点的概率?

设F(n)表示n次中改变了奇数次

设G(n)表示n次中改变了偶数次

那么,G(n)=1-F(n)且F(n)=F(n-1)*(1-p)+G(n-1)*p

可以解得F(n)=F(n-1)*(1-2p)+p,初始值为F(0)=0,F(1)=p

高中数学知识:左右两边同时除以(1-2p)^n,得到一个可以迭代的式子,根据边界条件,计算得:F(n)=0.5-0.5*(1-2p)^n


想通了,其实代码很简单的:

#include <cstdio>#include <algorithm>#include <cstring>#include <cstdlib>#include <math.h>#include <cmath>using namespace std;int t,n,x,y,z;double p,ans;double calc(int a,int b){return 1.0*b*b-1.0*(b-a)*(b-a)-(1.0)*(a-1)*(a-1);}int main(){//freopen("input.txt","r",stdin);scanf("%d",&t);for(int Case=1;Case<=t;Case++){ans=0;scanf("%d%d%d%d",&x,&y,&z,&n);for(int i=1;i<=x;i++)for(int j=1;j<=y;j++)for(int k=1;k<=z;k++){//概率等于符合条件的情况除以所有选择情况double p=calc(i,x)*calc(j,y)*calc(k,z)/x/x/y/y/z/z;ans+=0.5-0.5*pow(1-2*p,1.0*n);}printf("Case %d: %.8lf\n",Case,ans);}return 0;}


0 0
原创粉丝点击