HDU 4624 Endless Spin

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yzyyylx/article/details/81515404

题面

题意

给出一排球,初始全为白色,每次随机选择一段区间染黑,全黑时停止操作,问操作的期望次数。

做法

首先设pi表示i次完成的期望,这样答案就是1*p1+2*p2+3*p3…………
也就等于(p1+p2+p3………)+(p2+p3………)+(p3………)…….
令qi表示i次未全部染黑的期望次数,那么qi=p(i+1)+p(i+2)…………………..
因此答案就可以转化为q0+q1+q2+q3+q4+q5………………
可以考虑2^n(暂时这样想)枚举最后一步染黑的点,然后就可以知道之前可以染cnt段区间而不染黑最后一步要染黑的点,并算出其概率o,利用容斥算出每种情况对答案的贡献,就是cnt/(1/(1-o))*(-1)^(k+1).
然后发现答案仅与区间个数cnt,概率o以及白点数量的奇偶性有关,就可以dp:
dp[i][j][k]表示第i个点是白点时,此时有j种区间,且白点个数的奇偶性为k,最后统计对答案的贡献即可。
因为精度要求比较高,所以需要高精度。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

// ---------- decimal lib start ----------

const int PREC = 30;

class Decimal
{
    public:
        Decimal();
        Decimal(const std::string &s);
        Decimal(const char *s);
        Decimal(int x);
        Decimal(long long x);
        Decimal(double x);

        bool is_zero() const;

        // p (p > 0) is the number of digits after the decimal point
        std::string to_string(int p) const;
        double to_double() const;

        friend Decimal operator + (const Decimal &a, const Decimal &b);
        friend Decimal operator + (const Decimal &a, int x);
        friend Decimal operator + (int x, const Decimal &a);
        friend Decimal operator + (const Decimal &a, long long x);
        friend Decimal operator + (long long x, const Decimal &a);
        friend Decimal operator + (const Decimal &a, double x);
        friend Decimal operator + (double x, const Decimal &a);

        friend Decimal operator - (const Decimal &a, const Decimal &b);
        friend Decimal operator - (const Decimal &a, int x);
        friend Decimal operator - (int x, const Decimal &a);
        friend Decimal operator - (const Decimal &a, long long x);
        friend Decimal operator - (long long x, const Decimal &a);
        friend Decimal operator - (const Decimal &a, double x);
        friend Decimal operator - (double x, const Decimal &a);

        friend Decimal operator * (const Decimal &a, int x);
        friend Decimal operator * (int x, const Decimal &a);

        friend Decimal operator / (const Decimal &a, int x);

        friend bool operator < (const Decimal &a, const Decimal &b);
        friend bool operator > (const Decimal &a, const Decimal &b);
        friend bool operator <= (const Decimal &a, const Decimal &b);
        friend bool operator >= (const Decimal &a, const Decimal &b);
        friend bool operator == (const Decimal &a, const Decimal &b);
        friend bool operator != (const Decimal &a, const Decimal &b);

        Decimal & operator += (int x);
        Decimal & operator += (long long x);
        Decimal & operator += (double x);
        Decimal & operator += (const Decimal &b);

        Decimal & operator -= (int x);
        Decimal & operator -= (long long x);
        Decimal & operator -= (double x);
        Decimal & operator -= (const Decimal &b);

        Decimal & operator *= (int x);

        Decimal & operator /= (int x);

        friend Decimal operator - (const Decimal &a);

        // These can't be called
        friend Decimal operator * (const Decimal &a, double x);
        friend Decimal operator * (double x, const Decimal &a);
        friend Decimal operator / (const Decimal &a, double x);
        Decimal & operator *= (double x);
        Decimal & operator /= (double x);

        static const int len = PREC / 9 + 1;
        static const int mo = 1000000000;

        static void append_to_string(std::string &s, long long x);
    private:
        bool is_neg;
        long long integer;
        int data[len];

        void init_zero();
        void init(const char *s);
};

Decimal::Decimal()
{
    this->init_zero();
}

Decimal::Decimal(const char *s)
{
    this->init(s);
}

Decimal::Decimal(const std::string &s)
{
    this->init(s.c_str());
}

Decimal::Decimal(int x)
{
    this->init_zero();

    if (x < 0)
    {
        is_neg = true;
        x = -x;
    }

    integer = x;
}

Decimal::Decimal(long long x)
{
    this->init_zero();

    if (x < 0)
    {
        is_neg = true;
        x = -x;
    }

    integer = x;
}

Decimal::Decimal(double x)
{
    this->init_zero();

    if (x < 0)
    {
        is_neg = true;
        x = -x;
    }

    integer = (long long)x;
    x -= integer;

    for (int i = 0; i < len; i++)
    {
        x *= mo;
        if (x < 0) x = 0;
        data[i] = (int)x;
        x -= data[i];
    }
}

void Decimal::init_zero()
{
    is_neg = false;
    integer = 0;
    memset(data, 0, len * sizeof(int));
}

bool Decimal::is_zero() const
{
    if (integer) return false;
    for (int i = 0; i < len; i++)
    {
        if (data[i]) return false;
    }
    return true;
}

void Decimal::init(const char *s)
{
    this->init_zero();

    is_neg = false;
    integer = 0;

    // find the first digit or the negative sign
    while (*s != 0)
    {
        if (*s == '-')
        {
            is_neg = true;
            ++s;
            break;
        }
        else if (*s >= 48 && *s <= 57)
        {
            break;
        }
        ++s;
    }

    // read the integer part
    while (*s >= 48 && *s <= 57)
    {
        integer = integer * 10 + *s - 48;
        ++s;
    }

    // read the decimal part
    if (*s == '.')
    {
        int pos = 0;
        int x = mo / 10;

        ++s;
        while (pos < len && *s >= 48 && *s <= 57)
        {
            data[pos] += (*s - 48) * x;
            ++s;
            x /= 10;
            if (x == 0)
            {
                ++pos;
                x = mo / 10;
            }
        }
    }
}

void Decimal::append_to_string(std::string &s, long long x)
{
    if (x == 0)
    {
        s.append(1, 48);
        return;
    }

    char _[30];
    int cnt = 0;
    while (x)
    {
        _[cnt++] = x % 10;
        x /= 10;
    }
    while (cnt--)
    {
        s.append(1, _[cnt] + 48);
    }
}

std::string Decimal::to_string(int p) const
{
    std::string ret;

    if (is_neg && !this->is_zero())
    {
        ret = "-";
    }

    append_to_string(ret, this->integer);

    ret.append(1, '.');

    for (int i = 0; i < len; i++)
    {
        // append data[i] as "%09d"
        int x = mo / 10;
        int tmp = data[i];
        while (x)
        {
            ret.append(1, 48 + tmp / x);
            tmp %= x;
            x /= 10;
            if (--p == 0)
            {
                break;
            }
        }
        if (p == 0) break;
    }

    if (p > 0)
    {
        ret.append(p, '0');
    }

    return ret;
}

double Decimal::to_double() const
{
    double ret = integer;

    double k = 1.0;
    for (int i = 0; i < len; i++)
    {
        k /= mo;
        ret += k * data[i];
    }

    if (is_neg)
    {
        ret = -ret;
    }

    return ret;
}

bool operator < (const Decimal &a, const Decimal &b)
{
    if (a.is_neg != b.is_neg)
    {
        return a.is_neg && (!a.is_zero() || !b.is_zero());
    }
    else if (!a.is_neg)
    {
        // a, b >= 0
        if (a.integer != b.integer)
        {
            return a.integer < b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] < b.data[i];
            }
        }
        return false;
    }
    else
    {
        // a, b <= 0
        if (a.integer != b.integer)
        {
            return a.integer > b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] > b.data[i];
            }
        }
        return false;
    }
}

bool operator > (const Decimal &a, const Decimal &b)
{
    if (a.is_neg != b.is_neg)
    {
        return !a.is_neg && (!a.is_zero() || !b.is_zero());
    }
    else if (!a.is_neg)
    {
        // a, b >= 0
        if (a.integer != b.integer)
        {
            return a.integer > b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] > b.data[i];
            }
        }
        return false;
    }
    else
    {
        // a, b <= 0
        if (a.integer != b.integer)
        {
            return a.integer < b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] < b.data[i];
            }
        }
        return false;
    }
}

bool operator <= (const Decimal &a, const Decimal &b)
{
    if (a.is_neg != b.is_neg)
    {
        return a.is_neg || (a.is_zero() && b.is_zero());
    }
    else if (!a.is_neg)
    {
        // a, b >= 0
        if (a.integer != b.integer)
        {
            return a.integer < b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] < b.data[i];
            }
        }
        return true;
    }
    else
    {
        // a, b <= 0
        if (a.integer != b.integer)
        {
            return a.integer > b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] > b.data[i];
            }
        }
        return true;
    }
}

bool operator >= (const Decimal &a, const Decimal &b)
{
    if (a.is_neg != b.is_neg)
    {
        return !a.is_neg || (a.is_zero() && b.is_zero());
    }
    else if (!a.is_neg)
    {
        // a, b >= 0
        if (a.integer != b.integer)
        {
            return a.integer > b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] > b.data[i];
            }
        }
        return true;
    }
    else
    {
        // a, b <= 0
        if (a.integer != b.integer)
        {
            return a.integer < b.integer;
        }
        for (int i = 0; i < Decimal::len; i++)
        {
            if (a.data[i] != b.data[i])
            {
                return a.data[i] < b.data[i];
            }
        }
        return true;
    }
}

bool operator == (const Decimal &a, const Decimal &b)
{
    if (a.is_zero() && b.is_zero()) return true;
    if (a.is_neg != b.is_neg) return false;
    if (a.integer != b.integer) return false;
    for (int i = 0; i < Decimal::len; i++)
    {
        if (a.data[i] != b.data[i]) return false;
    }
    return true;
}

bool operator != (const Decimal &a, const Decimal &b)
{
    return !(a == b);
}

Decimal & Decimal::operator += (long long x)
{
    if (!is_neg)
    {
        if (integer + x >= 0)
        {
            integer += x;
        }
        else
        {
            bool last = false;
            for (int i = len - 1; i >= 0; i--)
            {
                if (last || data[i])
                {
                    data[i] = mo - data[i] - last;
                    last = true;
                }
                else
                {
                    last = false;
                }
            }
            integer = -x - integer - last;
            is_neg = true;
        }
    }
    else
    {
        if (integer - x >= 0)
        {
            integer -= x;
        }
        else
        {
            bool last = false;
            for (int i = len - 1; i >= 0; i--)
            {
                if (last || data[i])
                {
                    data[i] = mo - data[i] - last;
                    last = true;
                }
                else
                {
                    last = false;
                }
            }
            integer = x - integer - last;
            is_neg = false;
        }
    }
    return *this;
}

Decimal & Decimal::operator += (int x)
{
    return *this += (long long)x;
}

Decimal & Decimal::operator -= (int x)
{
    return *this += (long long)-x;
}

Decimal & Decimal::operator -= (long long x)
{
    return *this += -x;
}

Decimal & Decimal::operator /= (int x)
{
    if (x < 0)
    {
        is_neg ^= 1;
        x = -x;
    }

    int last = integer % x;
    integer /= x;

    for (int i = 0; i < len; i++)
    {
        long long tmp = 1LL * last * mo + data[i];
        data[i] = tmp / x;
        last = tmp - 1LL * data[i] * x;
    }

    if (is_neg && integer == 0)
    {
        int i;
        for (i = 0; i < len; i++)
        {
            if (data[i] != 0)
            {
                break;
            }
        }
        if (i == len)
        {
            is_neg = false;
        }
    }

    return *this;
}

Decimal & Decimal::operator *= (int x)
{
    if (x < 0)
    {
        is_neg ^= 1;
        x = -x;
    }
    else if (x == 0)
    {
        init_zero();
        return *this;
    }

    int last = 0;
    for (int i = len - 1; i >= 0; i--)
    {
        long long tmp = 1LL * data[i] * x + last;
        last = tmp / mo;
        data[i] = tmp - 1LL * last * mo;
    }
    integer = integer * x + last;

    return *this;
}

Decimal operator - (const Decimal &a)
{
    Decimal ret = a;
    // -0 = 0
    if (!ret.is_neg && ret.integer == 0)
    {
        int i;
        for (i = 0; i < Decimal::len; i++)
        {
            if (ret.data[i] != 0) break;
        }
        if (i < Decimal::len)
        {
            ret.is_neg = true;
        }
    }
    else
    {
        ret.is_neg ^= 1;
    }
    return ret;
}

Decimal operator + (const Decimal &a, int x)
{
    Decimal ret = a;
    return ret += x;
}

Decimal operator + (int x, const Decimal &a)
{
    Decimal ret = a;
    return ret += x;
}

Decimal operator + (const Decimal &a, long long x)
{
    Decimal ret = a;
    return ret += x;
}

Decimal operator + (long long x, const Decimal &a)
{
    Decimal ret = a;
    return ret += x;
}

Decimal operator - (const Decimal &a, int x)
{
    Decimal ret = a;
    return ret -= x;
}

Decimal operator - (int x, const Decimal &a)
{
    return -(a - x);
}

Decimal operator - (const Decimal &a, long long x)
{
    Decimal ret = a;
    return ret -= x;
}

Decimal operator - (long long x, const Decimal &a)
{
    return -(a - x);
}

Decimal operator * (const Decimal &a, int x)
{
    Decimal ret = a;
    return ret *= x;
}

Decimal operator * (int x, const Decimal &a)
{
    Decimal ret = a;
    return ret *= x;
}

Decimal operator / (const Decimal &a, int x)
{
    Decimal ret = a;
    return ret /= x;
}

Decimal operator + (const Decimal &a, const Decimal &b)
{
    if (a.is_neg == b.is_neg)
    {
        Decimal ret = a;
        bool last = false;
        for (int i = Decimal::len - 1; i >= 0; i--)
        {
            ret.data[i] += b.data[i] + last;
            if (ret.data[i] >= Decimal::mo)
            {
                ret.data[i] -= Decimal::mo;
                last = true;
            }
            else
            {
                last = false;
            }
        }
        ret.integer += b.integer + last;
        return ret;
    }
    else if (!a.is_neg)
    {
        // a - |b|
        return a - -b;
    }
    else
    {
        // b - |a|
        return b - -a;
    }
}

Decimal operator - (const Decimal &a, const Decimal &b)
{
    if (!a.is_neg && !b.is_neg)
    {
        if (a >= b)
        {
            Decimal ret = a;
            bool last = false;
            for (int i = Decimal::len - 1; i >= 0; i--)
            {
                ret.data[i] -= b.data[i] + last;
                if (ret.data[i] < 0)
                {
                    ret.data[i] += Decimal::mo;
                    last = true;
                }
                else
                {
                    last = false;
                }
            }
            ret.integer -= b.integer + last;
            return ret;
        }
        else
        {
            Decimal ret = b;
            bool last = false;
            for (int i = Decimal::len - 1; i >= 0; i--)
            {
                ret.data[i] -= a.data[i] + last;
                if (ret.data[i] < 0)
                {
                    ret.data[i] += Decimal::mo;
                    last = true;
                }
                else
                {
                    last = false;
                }
            }
            ret.integer -= a.integer + last;
            ret.is_neg = true;
            return ret;
        }
    }
    else if (a.is_neg && b.is_neg)
    {
        // a - b = (-b) - (-a)
        return -b - -a;
    }
    else if (a.is_neg)
    {
        // -|a| - b
        return -(-a + b);
    }
    else
    {
        // a - -|b|
        return a + -b;
    }
}

Decimal operator + (const Decimal &a, double x)
{
    return a + Decimal(x);
}

Decimal operator + (double x, const Decimal &a)
{
    return Decimal(x) + a;
}

Decimal operator - (const Decimal &a, double x)
{
    return a - Decimal(x);
}

Decimal operator - (double x, const Decimal &a)
{
    return Decimal(x) - a;
}

Decimal & Decimal::operator += (double x)
{
    *this = *this + Decimal(x);
    return *this;
}

Decimal & Decimal::operator -= (double x)
{
    *this = *this - Decimal(x);
    return *this;
}

Decimal & Decimal::operator += (const Decimal &b)
{
    *this = *this + b;
    return *this;
}

Decimal & Decimal::operator -= (const Decimal &b)
{
    *this = *this - b;
    return *this;
}

// ---------- decimal lib end ----------

#define ll long long
#define db double
#define D Decimal

ll n=50,dp[60][3010][2],T;
D ans[60];

inline ll calc(ll u)
{
    return u*(u+1)/2;
}

int main()
{
    ll i,j,k,a;
    int b;
    D tmp;
    dp[0][0][0]=1;
    for(i=0; i<=n; i++)
    {
        for(j=0; j<=calc(n); j++)
        {
            if(dp[i][j][0])
            {
                for(k=i+1; k<=n; k++)
                {
                    dp[k][j+calc(k-i-1)][1]+=dp[i][j][0];
                }
            }
            if(dp[i][j][1])
            {
                for(k=i+1; k<=n; k++)
                {
                    dp[k][j+calc(k-i-1)][0]+=dp[i][j][1];
                }
            }
        }
    }
    for(i=1; i<=n; i++)
    {
        for(j=0; j<=i; j++)
        {
            for(k=0; k<=calc(n); k++)
            {
                if(dp[j][k][0])
                {
                    tmp=a=dp[j][k][0]*calc(i);
                    b=calc(i)-k-calc(i-j);
                    if(b) ans[i]-=tmp/b;
                }
                if(dp[j][k][1])
                {
                    tmp=a=dp[j][k][1]*calc(i);
                    b=calc(i)-k-calc(i-j);
                    if(b) ans[i]+=tmp/b;
                }
            }
        }
    }
    for(i=1; i<=n; i++) ans[i]+=5e-16;
    cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        cout<<ans[n].to_string(15)<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/yzyyylx/article/details/81515404
今日推荐