数学专题训练3
2014-02-28 20:15
134 查看
这次是概率专练
选的题都比较基础。。因为我对概率的感觉很不到位啊啊啊啊
题目一:wikioi计算概率
地址:http://www.wikioi.com/problem/1533/
这个就是古典概型嘛。。。先枚举选的第一根。。。然后再求出第选二根后和小于等于l的方案个数。然后答案很自然就是 这些方案个数的和/n*(n-1)了。。
考虑到n稍大。。求方案数不能直接暴力。。。可以选择二分来求(要注意选的第二根不能与第一根一样。。所以二分后还要判断下这些可选的木棍是否包含了第一根,包含了的话减去)
第二题:rqnoj矩阵粉刷
地址:http://www.rqnoj.cn/problem/717
rq的某次月赛题。。。当时我是第一次参加网赛。。结果一道都不会 T_T
其实这题的题意我觉得不是太清楚。。。说的随机选两个点。。。其实选的这两个点可以是一个。。然后对应的矩形就是一个小方格了
期望方块数自然就是 每个方块的被刷到的概率*权值1 的和。
但是要粉刷k次。。。不好直接求哪个小方格被刷的概率。。。于是可以求某次不被刷的概率 p,然后1-p^k就是被刷的概率啦
然后某次不被刷的概率又要用1-某次被刷的概率来求。。
考虑到这样一个问题:对于每个方块。。。包含了它的矩形一定有两个相对的顶点在它的坐上方和右下方。。。(包括它本身所在坐标)
然后这样的矩形数基本上就是 左上角点横坐标可选方案数*纵坐标可选方案数*右下角点横坐标可选方案数*纵坐标可选方案数。
对于不为一个或一行一列的矩形。。。有四种选点的方式会选到它,对于是一行或一列的矩形只有两种,对于只有一格的矩形(也就是正好是这一格本身)只统计了一次。。。
于是我们就枚举方块(i,j)
其一次被粉刷的方案数为 4*i*j*(w-i+1)*(h-j+1)-2*(i*(w-i+1)+j*(h-j+1))+1 (先全当成普通的矩形,然后减去为一行或一列时多计算的次数,再加上多扣了的当一个格子时的次数),概率就是 上面那个式子/w*w*h*h
这题基本上就这样了。。。
题目三:rqnoj bomb
地址:http://www.rqnoj.cn/problem/691
我觉得稍微有点高端的题。。。纠结了很久(当然对大神们来说还是水到爆啦)
这道题是一道与期望有关的dp
状态这么设计:dp[i]表示剩i个精灵时的期望操作次数(我开始设计成减少i个的期望。。。结果纠结半天)
然后就可以得出这样一个方程:
dp[i]=(dp[i]*p[0]+dp[i-1]*p[1]+dp[i-2]*p[2]+....+dp[i-5]*p[5])+1;
直接用这个方程来递推的话。。。当然不行。。。因为左右都有dp[i];
所以移个项整理一下...变成dp[i]=p[1]/(1-p[0])*dp[i-1]+...+p[5]/(1-p[0])*dp[i-5]+1/(1-p[0]);
边界是这样的:对于i<m,dp[i]=0;
考虑到数据范围有点大。。。这个递推又是线性的。于是就可以想到用矩阵乘法来优化。。。
然后基本就没什么难点了
选的题都比较基础。。因为我对概率的感觉很不到位啊啊啊啊
题目一:wikioi计算概率
地址:http://www.wikioi.com/problem/1533/
这个就是古典概型嘛。。。先枚举选的第一根。。。然后再求出第选二根后和小于等于l的方案个数。然后答案很自然就是 这些方案个数的和/n*(n-1)了。。
考虑到n稍大。。求方案数不能直接暴力。。。可以选择二分来求(要注意选的第二根不能与第一根一样。。所以二分后还要判断下这些可选的木棍是否包含了第一根,包含了的话减去)
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<iostream> using namespace std; int n,ll; int len[100000+10]; double ans=0; int main() { scanf("%d%d",&n,&ll); for(int i=1;i<=n;i++)scanf("%d",&len[i]); sort(len+1,len+n+1); for(int i=1;i<=n;i++) { int l=1,r=n; while(l<r) { int mid=l+r+1>>1; if(len[mid]+len[i]>ll)r=mid-1; else l=mid; } if(l>=i) { l--; } if(l==1&&len[1]+len[i]>ll)l--; ans=ans+l*1.0/(n-1); } printf("%.2f\n",ans/n); return 0; }
第二题:rqnoj矩阵粉刷
地址:http://www.rqnoj.cn/problem/717
rq的某次月赛题。。。当时我是第一次参加网赛。。结果一道都不会 T_T
其实这题的题意我觉得不是太清楚。。。说的随机选两个点。。。其实选的这两个点可以是一个。。然后对应的矩形就是一个小方格了
期望方块数自然就是 每个方块的被刷到的概率*权值1 的和。
但是要粉刷k次。。。不好直接求哪个小方格被刷的概率。。。于是可以求某次不被刷的概率 p,然后1-p^k就是被刷的概率啦
然后某次不被刷的概率又要用1-某次被刷的概率来求。。
考虑到这样一个问题:对于每个方块。。。包含了它的矩形一定有两个相对的顶点在它的坐上方和右下方。。。(包括它本身所在坐标)
然后这样的矩形数基本上就是 左上角点横坐标可选方案数*纵坐标可选方案数*右下角点横坐标可选方案数*纵坐标可选方案数。
对于不为一个或一行一列的矩形。。。有四种选点的方式会选到它,对于是一行或一列的矩形只有两种,对于只有一格的矩形(也就是正好是这一格本身)只统计了一次。。。
于是我们就枚举方块(i,j)
其一次被粉刷的方案数为 4*i*j*(w-i+1)*(h-j+1)-2*(i*(w-i+1)+j*(h-j+1))+1 (先全当成普通的矩形,然后减去为一行或一列时多计算的次数,再加上多扣了的当一个格子时的次数),概率就是 上面那个式子/w*w*h*h
这题基本上就这样了。。。
#include<cstdlib> #include<cmath> #include<cstring> #include<iostream> #include<cstdio> #include<algorithm> using namespace std; long long k,w,h; double ans=0; double qpow(double d,int c) { if(c==0)return 1; if(c==1)return d; double ret=qpow(d,c/2); ret=ret*ret; if(c&1)ret=ret*d; return ret; } int main() { scanf("%lld%lld%lld",&k,&w,&h); long long s=w*w*h*h; for(int i=1;i<=w;i++) { for(int j=1;j<=h;j++) { double tem=i*(w-i+1)*j*(h-j+1)*4-2*(i*(w-i+1)+j*(h-j+1))+1; tem=tem/s; ans+=1-qpow(1-tem,k); } } printf("%.0f\n",ans); return 0; }
题目三:rqnoj bomb
地址:http://www.rqnoj.cn/problem/691
我觉得稍微有点高端的题。。。纠结了很久(当然对大神们来说还是水到爆啦)
这道题是一道与期望有关的dp
状态这么设计:dp[i]表示剩i个精灵时的期望操作次数(我开始设计成减少i个的期望。。。结果纠结半天)
然后就可以得出这样一个方程:
dp[i]=(dp[i]*p[0]+dp[i-1]*p[1]+dp[i-2]*p[2]+....+dp[i-5]*p[5])+1;
直接用这个方程来递推的话。。。当然不行。。。因为左右都有dp[i];
所以移个项整理一下...变成dp[i]=p[1]/(1-p[0])*dp[i-1]+...+p[5]/(1-p[0])*dp[i-5]+1/(1-p[0]);
边界是这样的:对于i<m,dp[i]=0;
考虑到数据范围有点大。。。这个递推又是线性的。于是就可以想到用矩阵乘法来优化。。。
然后基本就没什么难点了
#include<cstdio> #include<cmath> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; int n,m; double p[10]; double end=0; struct Mat { int x,y; double num[8][8]; Mat(){memset(num,0,sizeof(num));} Mat operator *(const Mat &b) { Mat c; c.x=x;c.y=b.y; for(int i=1;i<=x;i++) { for(int j=1;j<=b.y;j++) for(int k=1;k<=y;k++) { c.num[i][j]+=num[i][k]*b.num[k][j]; } } return c; } }start,single,ele; void readdata() { scanf("%d%d",&n,&m); for(int i=0;i<=m;i++)scanf("%lf",&p[i]); } double dp[5+10]; void pre() { start.x=6;start.y=1; dp[m]=1.0/(1-p[0]); for(int i=m+1;i<=4;i++) { for(int j=1;j<=5;j++)if(i-j>=0)dp[i]+=(dp[j]*p[i-j]/(1-p[0])); dp[i]+=1.0/(1-p[0]); } start.num[1][1]=dp[4]; start.num[2][1]=dp[3]; start.num[3][1]=dp[2]; start.num[4][1]=dp[1]; start.num[5][1]=dp[0]; start.num[6][1]=1.0/(1-p[0]); single.x=single.y=6; for(int i=1;i<=6;i++) { single.num[i][i]=1; } for(int i=1;i<=5;i++)ele.num[1][i]=p[i]/(1-p[0]); ele.x=ele.y=6; ele.num[1][6]=1;ele.num[2][1]=ele.num[3][2]=ele.num[4][3]=ele.num[5][4]=1; ele.num[6][6]=1; } Mat qpow(const Mat &d,int c) { if(c==0)return single; if(c==1)return d; Mat ret=qpow(d,c/2); ret=ret*ret; if(c&1)ret=ret*d; return ret; } int main() { readdata(); pre();//计算出dp[0]到dp[4]并存入start if(n<=4)printf("%.1f\n",dp ); else { Mat ans=qpow(ele,n-4); ans=ans*start; printf("%.1f\n",ans.num[1][1]); } return 0; }
相关文章推荐
- 数学专题训练2
- 训练指南——数学专题一的总结
- 数学专题训练4
- [专题训练]数论专题1
- uva 数学专题入门
- 线段树专题#6_蒟蒻训练历程记录_HDU 2705 Billboard_单点更新
- 小学期acm训练第一发(简单数学题)
- 数论专题训练K
- 数论专题训练2016.3.21
- AC自动机专题训练
- 数学专题小结:FFT算法
- CQUPT 2018 寒假训练 DIV2 (2)数学基础题解
- 周六日常训练,背包dp,树形dp,简单dp以及很多数学?
- 搜索专题训练hdu2510符号三角形
- 英语六级翻译训练:教育专题
- HNCU专题训练_线段树(2)
- HDU上的专题训练(背包问题-线段树+树状数组+DP优化+网络流+字符匹配+最短路+矩阵乘法+搜索专题++)
- 训练指南第二章数学有关知识
- 数学专题1
- 线段树专题#1_蒟蒻训练历程记录_HDU1166