天天看點

Topcoder SRM 660 DIV1 500 Privateparty(數學,容斥)

題意:

N個人參加宴會,現在知道每個參加宴會的一些條件vector_a,vector_a[i]表示i參加宴會的條件為:必須在vector_a[i]前面參加,否則就會拒絕參加;若vector_a[i]=i表示i對順序沒有要求。現在讓你随機安排N個人參加宴會的順序,求可以接收宴會邀請的人的數量的期望。

分析:

這種求期望的問題,往往轉化為單獨個體的機率問題,然後所有個體的機率之和,即為期望。

是以,從每個人來單獨考慮。

這裡用到了容斥的思想:

對于第i個人是否來參加聚會,受到一些人的影響,他們是:w1,w2,w3....wk。其中w1==i,w1讨厭w2,w2讨厭w3,...wk讨厭w1到wk-1的某個人。

第i個人參加聚會的機率為:

+包含集合w1的機率

-包含集合(w2,w1),(w2比w1先來)的機率:

+包含集合(w3,w2,w1),(w3比w2先來,w2比w1先來)的機率

.................

.................

+/-包含集合(wk,....w1)

代碼:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <sstream>
#define OUT(x) cout << #x << ": " << (x) << endl
#define SZ(x) ((int)x.size())
#define FOR(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
typedef long long LL;
bool vis[55];
class Privateparty
{
public:
    double getexp(vector <int> a)
    {
        int n=a.size();
        double ans=0;
        int i,j;
        for(i=0;i<n;i++)
        {
            memset(vis,false,sizeof(vis));
            int now=i;
            int ix=0;
            while(!vis[now])
            {
                ix++;
                vis[now]=true;
                now=a[now];
            }
            double p=1;
            double fc=1;
            for(j=2;j<=ix;j++)
            {
                fc*=1.0/j;
                if(j&1)
                    p+=fc;
                else
                    p-=fc;
            }
            ans+=p;
        }
        return ans;
    }<pre name="code" class="html">}