[最大似然估计 MLE] Codeforces 802DEF Helvetic Coding Contest 2017 D. E. F. Marmots

26 篇文章 0 订阅
22 篇文章 0 订阅

MLE

最大似然估计可以通过观察数据来估计出随机的模型和参数
最大似然估计(Maximum likelihood estimation)
Maximum likelihood estimation

大概就是从所有可能的参数和模型中,选出概率最大的那一组模型,作为估计的模型和参数

相关的还有一个最大后验估计(MAP),我没看过

然后就很好写了

D
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double ld;

ld fac[200005],ln[200005];

inline ld Poi(int x,int P){
  return x*ln[P]-P-fac[x];
}
inline ld Uni(int x,int P){
  if (x>2*P) return -1e20;
  return -ln[2*P+1];
}

const int N=255;

#define read(x) scanf("%d",&(x))

int T;
int a[N];

int main(){
  int T;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(T);
  fac[0]=0;
  for (int i=1;i<=200000;i++) fac[i]=fac[i-1]+(ln[i]=log(i));
  while (T--){
    for (int i=1;i<=250;i++) read(a[i]);
    int t=-1,P=-1; ld maxv=-1e20;
    for (int p=10;p<=1000;p++){
      ld ret=0;
      for (int i=1;i<=250;i++)
    ret+=Poi(a[i],p);
      if (ret>maxv) maxv=ret,t=0,P=p;
      ret=0;
      for (int i=1;i<=250;i++)
    ret+=Uni(a[i],p);
      if (ret>maxv) maxv=ret,t=1,P=p;
    }
    if (t==0)
      printf("poisson\n");
    else
      printf("uniform\n");
    //fprintf(stderr,"%d\n",P);
  }
  return 0;
}
E
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double ld;

ld fac[200005],ln[200005];

inline ld Poi(int x,int P){
  return x*ln[P]-P-fac[x];
}
inline ld Uni(int x,int P){
  if (x>2*P) return -1e20;
  return -ln[2*P+1];
}

const int N=255;

#define read(x) scanf("%d",&(x))

int T;
int a[N];

int main(){
  int T;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(T);
  fac[0]=0;
  for (int i=1;i<=200000;i++) fac[i]=fac[i-1]+(ln[i]=log(i));
  while (T--){
    for (int i=1;i<=250;i++) read(a[i]);
    int t=-1,P=-1; ld maxv=-1e20;
    for (int p=10;p<=1000;p++){
      ld ret=0;
      for (int i=1;i<=250;i++)
    ret+=Poi(a[i],p);
      if (ret>maxv) maxv=ret,t=0,P=p;
      ret=0;
      for (int i=1;i<=250;i++)
    ret+=Uni(a[i],p);
      if (ret>maxv) maxv=ret,t=1,P=p;
    }
    /*if (t==0)
      printf("poisson\n");
    else
    printf("uniform\n");*/
    printf("%d\n",P);
  }
  return 0;
}
F
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef double ld;

ld fac[200005],ln[200005];

inline ld Poi(int x,int P){
  x+=P;
  return x*ln[P]-P-fac[x];
}
inline ld Uni(int x,int P){
  x+=P;
  if (x<0 || x>2*P) return -1e20;
  return -ln[2*P+1];
}

const int N=255;

#define read(x) scanf("%d",&(x))

int T;
int a[N];

int main(){
  int T;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(T);
  fac[0]=0;
  for (int i=1;i<=200000;i++) fac[i]=fac[i-1]+(ln[i]=log(i));
  while (T--){
    for (int i=1;i<=250;i++) read(a[i]);
    int t=-1,P=-1; ld maxv=-1e20;
    for (int p=1;p<=1000;p++){
      ld ret=0;
      for (int i=1;i<=250;i++)
    ret+=Poi(a[i],p);
      if (ret>maxv) maxv=ret,t=0,P=p;
      ret=0;
      for (int i=1;i<=250;i++)
    ret+=Uni(a[i],p);
      if (ret>maxv) maxv=ret,t=1,P=p;
    }
    if (t==0)
      printf("poisson\n");
    else
      printf("uniform\n");
    //printf("%d\n",P);
  }
  return 0;
}

乱搞

然后就是我在看到题解前的乱搞做法了

D

求出平均数,估计出 P ,然后因为值域大概是[0,2P],我统计下落在 [0,P3] 之间的数量来估计

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

#define read(x) scanf("%d",&(x))

const int N=10005;

int n,a[N];
int cnt[N];

int main(){
  int T;
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(T);
  while (T--){
    cl(cnt); int ex=0;
    for (int i=1;i<=250;i++) read(a[i]),cnt[a[i]]++,ex+=a[i];
    ex/=250;
    int tot=0;
    for (int i=1;i<=ex/3;i++)
      tot+=cnt[i];
    if (tot<250/6-25)
      printf("poisson\n");
    else
      printf("uniform\n");
  }
  return 0;
}
E

现在要求 P ,先判断是哪种分布
如果是均匀分布,那么取最大值的一半,可以算出出错的概率是极低的
如果是高斯分布,那么直接输平均数吧

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<ctime>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

#define read(x) scanf("%d",&(x))

const int N=10005;

int n,a[N];
int cnt[N];

int main(){
  int T; srand(time(0));
  read(T);
  while (T--){
    cl(cnt); double ex=0;
    for (int i=1;i<=250;i++) read(a[i]),cnt[a[i]]++,ex+=a[i];

    ex/=250;

    int tot=0;
    for (int i=1;i<=ex/3;i++)
      tot+=cnt[i];

    if (tot<250/6-25){

    }else{
      ex=0;
      for (int i=1;i<=250;i++)
    ex=max(ex,(double)a[i]);
      ex/=2.0;
    }

    printf("%.0lf\n",ex);
  }
  return 0;
}

F

分布大概是在[P,P],但高斯分布是可以 [P,]
通过最大最小值大概估计出 P
然后对于P大的,我直接统计 |a|P2 |a|>P2 的数量的比值
如果 P 比较小,可能会出错,尤其是P=1,那么就先判一下最大值是不是大于最小值

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<ctime>
#include<cmath>
#include<cassert>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;

#define read(x) scanf("%d",&(x))

const int N=10005;

int a[N];

int main(){
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  int T; srand(time(0));
  read(T);
  while (T--){
    double ex=0;
    int minv=1<<30,maxv=-1<<30;
    int n=250;
    for (int i=1;i<=250;i++){
      if (!(~read(a[i]))) {n=i-1; break;}
      minv=min(minv,a[i]); maxv=max(maxv,a[i]);
    }
    int x=(abs(minv)+abs(maxv))/4;
    int c0=0,c1=0;
    for (int i=1;i<=n;i++)
      if (abs(a[i])<=x)
    c0++;
      else
    c1++;
    if (minv>=-10){
      if (abs(maxv)>abs(minv))
    printf("poisson\n");
      else{
    if (c1==0 || c0/c1>1.3)
      printf("poisson\n");
    else
      printf("uniform\n");
      }
      continue;
    }
    if (c1==0 || c0/c1>1.3)
      printf("poisson\n");
    else
      printf("uniform\n");
  }
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值