1. 程式人生 > >【NOIP2016提高A組8.12】禮物

【NOIP2016提高A組8.12】禮物

lld 技術 log urn esp sdn 分享圖片 typedef def

題目

夏川的生日就要到了。作為夏川形式上的男朋友,季堂打算給夏川買一些生日禮物。
商店裏一共有種禮物。夏川每得到一種禮物,就會獲得相應喜悅值Wi(每種禮物的喜悅值不能重復獲得)。
每次,店員會按照一定的概率Pi(或者不拿出禮物),將第i種禮物拿出來。季堂每次都會將店員拿出來的禮物買下來。
眾所周知,白毛切開都是黑的。所以季堂希望最後夏川的喜悅值盡可能地高。
求夏川最後最大的喜悅值是多少,並求出使夏川得到這個喜悅值,季堂的期望購買次數。

分析

首先,因為Wi>0,顯然最大喜悅值為全選的情況。
註意到n“肥”常小。
考慮狀壓dp。
設S是二進制表示哪些禮物買過,\(F_S\)表示期望。
從後往前推,

技術分享圖片
然後移項得
技術分享圖片
這是出題人的標程

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;

#define N 2000000 + 10
typedef long long ll ;

double f[N] , P[N] ;
int n , m ;
ll ans ;

int main() {
    scanf( "%d" , &n ) ;
    for (int i = 1 ; i <= n ; i ++ ) {
        int a ;
        scanf( "%lf%d" , &P[i] , &a ) ;
        if ( P[i] > 0 ) ans += a ;
    }
    m = (1 << n) - 1 ;
    f[m] = 0 ;
    for (int s = m - 1 ; s >= 0 ; s -- ) {
        double sum = 0 ;
        for (int j = 0 ; j < n ; j ++ ) {
            if ( (s & (1 << j)) == 0 ) {
                sum += P[j+1] ;
                int _s = s | (1 << j) ;
                f[s] += P[j+1] * f[_s] ;
            }
        }
        f[s] ++ ;
        f[s] = f[s] / sum ;
    }
    printf( "%lld\n%.3lf\n" , ans , f[0] ) ;
    return 0 ;
}

【NOIP2016提高A組8.12】禮物