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
,然后因为值域大概是
#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
比较小,可能会出错,尤其是
#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;
}