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 _{T\subseteq 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} \rightarrow dp_{k,j+(k-i)(k-i-1)/2,1/0}$$
假设位置$0$和位置$n+1$也有球并强制它们染色
需要高精实数的加减法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }