LUOGU P1291 [SHOI2002]百事世界杯之旅 (期望dp)

传送门

解题思路

期望$dp$,今天才弄清楚啥时候正着推啥时候倒着推。。因为这个是期望步数,所以要倒着推,而期望值要正着推。这就相当于功率和时间的关系。。(机房内某个姓嘤的人说的)。那么这道题就变得一脸可做了,设$f[i]$表示还有$i$张牌没有收集的期望,那么考虑再抽一张,有$(n-i)/n$的概率抽到抽过的牌,有$i/n$的概率抽到没有抽过的牌。那么转移方程就是: $f[i]=f[i]*\dfrac{(n-i)}{n}+f[i-1]*\dfrac {i}{n}+1 $。但这样是没法继续写的,因为方程两边有同一个未知数,所以移项可得 $f[i]=f[i-1]+\dfrac{n}{i}$。

输出的格式真的6,因为要输出分数,所以要记下来分母和分子,用一个结构体记录,重载一下$+$就行了。








#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

using namespace std;
const int MAXN = 35;
typedef long long LL;

int n,cnt,num;
struct Node{
    LL a,b;
    Node(LL u=0,LL v=1) {a=u;b=v;}
    friend Node operator+(const Node A,const Node B){
        Node ret;ret.a=ret.b=0;
        ret.a=A.a*B.b+A.b*B.a;
        ret.b=A.b*B.b;
        LL gcd=__gcd(ret.a,ret.b);
        ret.a/=gcd;ret.b/=gcd;
        return ret;
    }
}f[MAXN];

//f[i]=f[i-1]*i/n+f[i]*(n-i)/n+1
//f[i]=f[i-1]+n/i 

int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
        f[i]=f[i-1]+Node(n,i);
    if(f[n].b==1) printf("%lld",f[n].a);
    else{
        LL now=f[n].a/f[n].b;
        LL fuck=now;
        while(fuck) {cnt++;fuck/=10;}
        for(int i=1;i<=cnt;i++) putchar(' ');
        printf("%lld\n",f[n].a-now*f[n].b);
        if(now) printf("%lld",now);
        LL shit=f[n].b;
        while(shit) {num++;shit/=10;}
        for(int i=1;i<=num;i++) putchar('-');putchar('\n');
//        printf("-\n");
        for(int i=1;i<=cnt;i++) putchar(' ');
        printf("%lld\n",f[n].b);
    }    
    return 0;
}
View Code

 

猜你喜欢

转载自www.cnblogs.com/sdfzsyq/p/9757256.html