SD省队集训2019Day10之“Distribution”

Distribution(distribution)

题目描述

\(p\) 是一个 \((0, 1)\) 之间的实数,\(n\) 是一个 \([1, 100]\) 之间的正整数。
\(X_1 , X_2 , . . . , X_n\)\(n\) 个独立的随机变量,并且满足 \(Pr(X_i = 1) = p, Pr(X_i = 0) = 1 − p\),考虑下面的随机变量\(X =\frac{X_1 + X_2 + · · · + X_n + u − np}{\sqrt{np(1 − p)}}\)
其中 \(u\) 是在 \([−0.5, 0.5]\) 之间均匀分布的实数随机变量,与 \(X_i\) 独立。
现在对于某个 \(n\) 给出了很多个 \(X\) 的取值,想让你猜出 \(n\) 的值。

做法

对于n的100种可能的值,计算概率,取最大的一个输出。

计算方法要用到bayes公式:(D表示随机出来\(X_i\)的取值)
\[ \because P(D)*P(n=a|D)=P(n=a)*P(D|n=a)\\ \therefore P(n=a|D)=\frac{P(D|n=a)*P(n=a)}{P(D)} \]
因为n是随机取的,所以\(P(n=a)\)是定值。同样\(P(D)\)也是定值。所以我们算一下\(n=a\)时能随机出来D(输入的\(X_i\)的值的情况)的概率就可以。

代码

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cassert>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
// head
// 正文开始
int _,T;
double dp[110][110],x,prob[110],p,coef[110];
int main() {
    freopen("distribution.in","r",stdin);
    freopen("distribution.out","w",stdout);
    scanf("%d",&_);
    scanf("%lf",&p);
    dp[0][0]=1;
    rep(i,0,100) rep(j,0,i+1) dp[i+1][j+1]+=dp[i][j]*p,dp[i+1][j]+=dp[i][j]*(1-p);
    //解释一下这个方程:
    //dp[i][j]表示i个数中随机出j个1的概率
    //那么要么就是dp[i-1][j-1]再随机出来一个1,要么就是dp[i-1][j]在随机出来一个0。
    //所以就是dp[i][j]=dp[i-1][j-1]*p+dp[i-1][j]*(1-p)
    //这里稍微改变了循环方式,可以避免不必要的计算,优化常数
    
    rep(i,1,101) rep(j,0,i+1) dp[i][j]=log(dp[i][j]);
    rep(n,1,101) coef[n]=0.5*log(n*p*(1-p));
    for (;_;_--) {
        scanf("%d",&T);
        rep(n,1,101) prob[n]=0;
        rep(i,0,T) {
            scanf("%lf",&x);
            rep(n,1,101) {
                int rr=floor(x*sqrt(n*p*(1-p))+n*p+0.5);
                if (rr<0||rr>n) prob[n]+=-1e9/*避免浮点数误差*/; else prob[n]+=dp[n][rr]+coef[n];
            }
        }
        printf("%d\n",max_element(prob+1,prob+101)-prob);
    }
}

猜你喜欢

转载自www.cnblogs.com/water-lift/p/10993794.html