HDU 4873 题解

来源:互联网 发布:思科通过mac地址查询ip 编辑:程序博客网 时间:2024/06/17 03:06

原题解传送门
感谢大佬的博客教会我解这道题.不过我觉得推式子的过程可以再简化一下.

题目大意

在一个D维的空间里,每一维的坐标轴都有一条平行于它的线段.这个线段的两个端点,除了这一维的坐标不同之外,其余维度的坐标均相同。两个端点在每一维的坐标都是[0,n-1]之间的随机整数,且两个端点不重合.两条线段交于一点时,XXX会获得一点能量,问:XXX获得的能量值的期望是多少?

输入

多组数据,每组一行,两个数,分别为n,D;

输出

每组一行,一个既约分数p/q。如果分母为1,则只输出分子。

数据范围

1<n109D9910

题解

其实就是一个计数问题,主要难点在于相交情况的统计.

首先,每条线段都是平行于某一坐标轴的,那么两条相交线段最多只能有两维的坐标是不同的.不妨设这两维是X,Y;
考虑一条平行于X轴(或Y轴)的线段有多少种可能呢?nC2n=n2(n1)2
那么两条线段组合起来的情况就有:n4(n1)24种。
那么相交的情况呢?设两条线段的交点为(i,j),两条线段分别为a,b其中a平行于x轴,b平行于y轴.
那么由于a.start.x<=ia.end.x>=ia.start.x!=a.end.xa.y=j 
所以a的可能情况就有(ni)(i+1)1=(i+1)n(i2+i+1)种.
b的情况同理.
于是相交的情况:

num=i=0n1j=0n1[(i+1)n(i2+i+1)][(j+1)n(j2+j+1)]

num=(i=0n1[(i+1)n(i2+i+1)] )2=(ni=1nii=1ni2+i=0n1i )2=(n2(n+1)2n(n+1)(2n+1)6+n(n1)2)2=(n3+3n24n6)2

所以对于一组(X,Y)出现交点的概率为:
P=num(n4(n1)24)=(n+4)29n2(n>1)

所以期望值:
E=C2D1nD2P=C2D1nD2(n+4)29n2=(n1)n(n+4)218nD

题目要求输出分数,但是分子分母都会爆long long,于是需要用高精度计算分子分母。鉴于高精度约分不方便,我们可以把这些因式先约分至最简,然后再乘起来.

Code

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;#define MAXN 1200struct big{    int x[MAXN],len;    big()    {        memset(x,0,sizeof(x));        len=0;    }    big operator = (char* s)    {         len=strlen(s);         for(int i=1;i<=len;i++)         {             x[i]=s[len-i]-'0';         }         return *this;    }    big operator = (int num)    {        char s[MAXN];        sprintf(s,"%d",num);        return *this=s;    }    void print()    {        for(int i=len;i>=1;i--)        {            printf("%d",x[i]);        }        return ;    }    big operator * (const big& b) const    {        big c=big();        c.len=len+b.len;        for(int i=1;i<=len;i++)        {            for(int j=1;j<=b.len;j++)            {                c.x[i+j-1]+=x[i]*b.x[j];            }        }        for(int i=1;i<=c.len;i++)        {            c.x[i+1]+=c.x[i]/10;            c.x[i]%=10;        }        for(;c.len>1&&!c.x[c.len];c.len--);        return c;    }};int n,d;inline int gcd(int x,int y){    int t;    while(y)    {        t=x;        x=y;        y=t%y;    }    return x;}int A[MAXN],B[MAXN],flag;int main(){    while(scanf("%d%d",&n,&d)==2)    {        A[1]=d;        A[2]=d-1;        A[3]=A[4]=n+4;//分子        B[1]=18;        for(int i=2;i<=d+1;i++)        {            B[i]=n;        }//分母        for(int i=1;i<=4;i++)        {            for(int j=1,tt;j<=d+1&&A[i]>1;j++)            {                if(B[j]>1)                {                    tt=gcd(A[i],B[j]);                    A[i]/=tt;                    B[j]/=tt;                }            }        }//因为数据很小直接暴力约分,有些题解用的分解质因数        big p,q;        p=1;        for(int i=1;i<=4;i++)        {            q=A[i];            p=p*q;        }        p.print();        p=1;        flag=1;        for(int i=1;i<=d+1;i++)        {            q=B[i];            p=p*q;            if(B[i]>1)            {                flag=0;            }        }        if(!flag)        {            printf("/");            p.print();        }        putchar('\n');    }    return 0;}
原创粉丝点击