有一群无聊的人,共n个,编号1-n,他们互相发信,共有m个发信请求,每个请求ai,bi表示标号为ai希望将1封信发给bi,每个人有且只有一次到达邮筒的机会,到达邮筒时,他们先接收邮箱中发给自己的信,然后他们会将自己要发的信放在邮筒里。
每个人在(pi,qi)之间随机一个时间到达,这之中每个时间被选中的概率均等,此时间为0,100之间的实数。
收到信的总数的期望是多少。
输入格式:
第一行两个整数n,m.。分别表示人数和待发信件数(请求数)。
接下来m行,每行两个整数ai,bi,ai希望将信发给bi。
接下来n行,每行两个实数pi,qi,i的时间将在(pi,qi)中生成。
输出格式:
输出一行一个实数,表示最终信件总数的期望(保留2位小数)。
样例输入:
样例输出:
时间限制:
5S
空间限制:
256M
提示:
10%的数据1<=n,m<=5
30%的数据1<=n,m<=1000
另外10%的数据ai < bi
100%的数据1<=n,m<=500000,1<=ai,bi<=n且ai≠bi,0<pi+0.1<=qi<100。
..考场一百个人A。是比较水。
5S时限不知道干什么的。。
期望是可加的,单独考虑每一封发出的信,收到这封信的期望是多少之和就行了。
然后随便YY一下..分一下类.用长度加权搞一搞。。
然后就能写出一个很优美的代码了。。
#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
const int MAX_N=500005;
double x[MAX_N],y[MAX_N];
int A[MAX_N],B[MAX_N],n,m;
double ans=0;
double calc(int a,int b){
bool sp=x[a]>x[b]?a^=b^=a^=b,1:0;
double res=0;
if (y[a]<=x[b]) res=1;else
if (y[a]<=y[b]) res=1-(y[a]-x[b])*(y[a]-x[b])/(2*(y[a]-x[a])*(y[b]-x[b]));
else res=((x[b]-x[a])+(y[b]-x[b])/2)/(y[a]-x[a]);
return sp?1-res:res;
}
int main(){
scanf("%d%d",&m,&n);
rep(i,1,n) scanf("%d%d",&A[i],&B[i]);
rep(i,1,m) scanf("%lf%lf",&x[i],&y[i]);
rep(i,1,n) ans+=calc(A[i],B[i]);
printf("%.2f\n",ans);
}
送上原题解一份:
本题10%可以直接用随机统计的方法。
即每个数在(pi,qi)间随机一个数,然后统计答案,最后求平均。只要次数足够就能求出解。
期望得分10-100
来数学化本题模型。
定义一组随机变量ri(1<=i<=m)
若第i个不等式成立,则ri为1,否则为0
所以我们要求的就是E(r1+r2+r3+...+rn)
而根据期望的和等于和的期望
E(r1+r2+..+rn)=Er1+Er2+...Ern
于是问题化为求E(ri)
E(ri)=1*p(aAi<aBi)
怎么求呢?为了讨论方便,我们设x=Ai,Y=i
此时我们要求在(px,qx)之间生成的随机数小于(py,qy)所生成的随机数的概率r。
1.若px>qy,r=0;
2.若qx<py,r=1;
3.若px<py<qx<qy,
r=?
下面记ai在(U,V)间有概率为F(i,u,v)
那么一述r=f(x,px,py)+f(x,py,qx)*(f(y,py,qx)*0.5+f(y,qx,qy)
4.若py<px<qx<qy
r=f(y,px,qx)*0.5+f(y,qx,qy)
这样讨论下去是可以得到结果的,期望得分100
但这么做显然太繁琐,而且易出错。
常数也太大。
这里给出一种稍微简单的方法。
通过之前的讨论我们发现,当随机量ax落在一个中间没有任何端点的区间时,其小于bx的概率的变化是线性的。
所以不妨枚举ax可能的顶点
然后判断是否可能,若可能,和前面一个可能的顶点的值求平均然后乘上落在其中的概率(这里的值指小于bx的概率)
每个不等式计算的效率为O(1),因此总的效率为O(n+m)
期望得分100