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
原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14196682.html