HDU 4873 题解

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

题目大意

在一个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 1200
struct 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值