Endless spin

Endless spin

给你一段长度为[1..n]的白色区间,每次随机的取一个子区间将这个区间涂黑,问整个区间被涂黑时需要的期望次数。n<=50

这篇博客港的很好了,相信我没有什么好港的。注意这里的dp是第二种用法的dp。

#include <cstdio> 
using namespace std;

int T, n;
const int maxn=55;
long long f[maxn][2][maxn*maxn];

struct BigDouble{
    long long ip;  //整数部分 
    int a[maxn];
    BigDouble(){}
    BigDouble(long long x, long long y){
        ip=x/y; x=x%y;
        for (int i=0; i<maxn; ++i) x*=10, a[i]=x/y, x%=y; }
}E[maxn];
BigDouble operator+(const BigDouble &x, const BigDouble &y){
    BigDouble re; re.ip=x.ip+y.ip;
    for (int i=0; i<maxn; ++i) re.a[i]=x.a[i]+y.a[i];
    for (int i=maxn-1; i>0; --i) 
        if (re.a[i]>9) ++re.a[i-1], re.a[i]-=10;
    if (re.a[0]>9) ++re.ip, re.a[0]-=10;
    return re; 
}
BigDouble operator-(const BigDouble &x, const BigDouble &y){
    BigDouble re; re.ip=x.ip-y.ip;
    for (int i=0; i<maxn; ++i) re.a[i]=x.a[i]-y.a[i];
    for (int i=maxn-1; i>0; --i)
        if (re.a[i]<0) --re.a[i-1], re.a[i]+=10;
    if (re.a[0]<0) --re.ip, re.a[0]+=10;
    return re;
}
void print(BigDouble x){
    BigDouble y; if (x.a[15]>4) y.a[14]=1;
    y=y+x;
    printf("%lld.", y.ip);
    for (int i=0; i<15; ++i) printf("%d", y.a[i]); 
    puts(""); return; }

int main(){
    scanf("%d", &T);
    f[0][0][0]=1;
    for (int i=0; i<=50; ++i)  //当前考虑前i个数 ,第i个数是在集合内的 
        for (int j=0; j<=(i+1)*i/2; ++j){  // 区间个数为j 
            for (int k=i+1; k<=50; ++k)  //设第k个数 也在集合内 
                f[k][1][j+(k-i)*(k-i-1)/2]+=f[i][0][j];
            for (int k=i+1; k<=50; ++k)
                f[k][0][j+(k-i)*(k-i-1)/2]+=f[i][1][j];
        }
    int A, all;
    for (int i=1; i<=50; ++i)
        for (int j=0; j<=i; ++j){  //第j个数在子集内 
            for (int k=0; k<=(j+1)*j/2; ++k){  //k个区间 
                A=(k+(i-j+1)*(i-j)/2); all=(i*(i+1)/2);  //p=A/all;
                if (all==A) continue; 
                E[i]=E[i]-BigDouble(f[j][0][k]*all, all-A);
                E[i]=E[i]+BigDouble(f[j][1][k]*all, all-A);
            }
        }
    while (T--){ scanf("%d", &n); print(E[n]); }
    return 0;
}

转载于:https://www.cnblogs.com/MyNameIsPc/p/9598851.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值