• hdu4624 Endless Spin


    Description

    I spin it again and again,and throw it away finally.
    So now I have a row of n ball,named from 1 to n,each ball is white initially.
    At each step I randomly chose a interval [l, r] and paint all ball in this interval to black.
    It means every interval have a equal chance of being chosen.
    And I'll stop if all ball are black.What is the expected steps before I stop?

    Solution

    首先Min-Max容斥

    $$max(S)=sum _{Tsubseteq S}(-1)^{|T|-1} min(T) $$

    转化为求任意一个集合中至少选中一个点的最早时间,假设不包含集合中任何一点的区间个数为$k$,则时间为

    $$frac{n(n+1)/2}{n(n+1)/2-k} $$

    枚举每个子集是$O(2^n)$的,考虑枚举$k$,DP求有多少种子集使不包含集合中任何一点的区间个数为$k$,对集合大小分奇偶讨论

    $$dp_{i,j,0/1} ightarrow dp_{k,j+(k-i)(k-i-1)/2,1/0}$$

    假设位置$0$和位置$n+1$也有球并强制它们染色

    需要高精实数的加减法

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int T;
    long long dp[55][2505][2],p,n;
    struct GJ
    {
        long long a;
        int b[105];
        void add(long long x,long long y)
        {
            a+=x/y,x-=x/y*y;
            for(int i=1;i<=100;i++) x*=10,b[i]+=x/y,x-=x/y*y;
            for(int i=99;~i;i--) b[i]+=b[i+1]/10,b[i+1]%=10;
            a+=b[0],b[0]=0;
        }
    }ans,temp;
    inline long long read()
    {
        long long w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
        while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
        return w*f;
    }
    int main()
    {
        dp[0][0][0]=1,T=read();
        for(int i=0;i<=50;i++) for(int j=0;j<=2500;j++) for(int k=i+1;k<=51;k++) dp[k][j+(k-i)*(k-i-1)/2][1]+=dp[i][j][0],dp[k][j+(k-i)*(k-i-1)/2][0]+=dp[i][j][1];
        for(;T;T--)
        {
            for(int i=0;i<=100;i++) ans.b[i]=temp.b[i]=0;
            n=read(),p=n*(n+1)/2,ans.a=temp.a=0;
            for(int i=0;i<p;i++) ans.add(dp[n+1][i][0]*p,p-i),temp.add(dp[n+1][i][1]*p,p-i);
            for(int i=100;i;i--) ans.b[i]-=temp.b[i];
            for(int i=99;~i;i--) if(ans.b[i+1]<0) ans.b[i]--,ans.b[i+1]+=10;
            ans.a+=ans.b[0],ans.a-=temp.a,ans.b[0]=0;
            if(ans.b[16]>=5) ans.b[15]++;
            for(int i=14;~i;i--) ans.b[i]+=ans.b[i+1]/10,ans.b[i+1]%=10;
            ans.a+=ans.b[0],printf("%lld.",ans.a);
            for(int i=1;i<=15;i++) printf("%d",ans.b[i]);
            putchar(10);
        }
        return 0;
    }
    Endless Spin
  • 相关阅读:
    每天一个topic----route 设置
    每周一个topic IGMP -- 2013.08.13
    HTTP API 加签名规则
    gitbook 编辑手册
    phpMyAdmin 配置文档
    扒房源线索消息推送设计
    jetty 必知必会
    回溯法解决八皇后问题
    求m行n列个方格的正方形总数
    IOC和AOP的简单实现
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14196682.html
Copyright © 2020-2023  润新知