DTOJ 1486:分数(score)
【题目描述】
【输入】
第一行包含两个正整数N和P,表示选手的个数以及精度要求。
接下来的N行,每行包含一个0到100(闭区间)内的整数。
【输出】
输出一个实数,取P位有效数字,下取整。
【样例输入】
5 4
100
20
15
10
0
【样例输出】
195.2
【提示】
【分析】
这道题需要让你求出使偏差最小的难度和区分度的大小。根据题目下方的难度-区分度的图表,结合题意,可以发现偏差值与难度-区分度的关系为一个单峰函数。因此我们可以对其进行三分。由于有两个变量(难度,区分度),所以我们先固定一个变量,对另一个变量进行三分操作。在这里,我们最好先固定难度,先对区分度进行三分,求出当前难度下区分度最优的情况下的偏差值,然后根据偏差值的大小再对难度进行三分(也就是三分套三分的意思)。直接使用此方法即可。
【代码】
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-9;
long double df_lf=0.0,df_rt=15.0,d,df_lm,df_rm,ds_lf,ds_rt,ds_lm,ds_rm;
int a[30],n,p;
inline long double sigma ( long double dfcl,long double disp )
{
long double sum=0,idel=100;
for ( int i=1;i<=n;i++ )
{
long double score=100/(1+exp(dfcl-disp*a[i]));
if ( score<1e-12 ) sum+=(100.0-idel)*log(100/(100-score));
else if ( score>=100 ) sum+=(idel*log(100/score));
else sum+=(idel*log(100/score)+(100.0-idel)*log(100/(100-score)));
idel-=d;
}
return sum;
}
inline void print ( long double val )
{
long long w=1;
int ups=0,used=0;
while ( true )
{
if ( val/w<1 ) break;
w*=10,ups++;
}
long long res=(long long)(val*pow(10,10-ups)),highest=1000000000;
for ( int i=9;i>=10-p;i-- )
{
if ( i==9-ups ) putchar((i==9)?'0':'.');
cout<<res/highest;res%=highest;used++;highest/=10;
}
while ( used<ups ) putchar('0'),used++;
}
inline int read ( void )
{
int x=0;char ch=getchar();
while ( !isdigit(ch) ) ch=getchar();
for ( x=ch-48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+ch-48;
return x;
}
int main()
{
scanf("%d%d",&n,&p);d=100.0/(n-1);
for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]);
while ( df_rt-df_lf>eps )
{
df_lm=df_lf+(df_rt-df_lf)/3.0,df_rm=df_rt-(df_rt-df_lf)/3.0;
ds_lf=0.0,ds_rt=1.0;
while ( ds_rt-ds_lf>eps )
{
ds_lm=ds_lf+(ds_rt-ds_lf)/3.0,ds_rm=ds_rt-(ds_rt-ds_lf)/3.0;
if ( sigma(df_lm,ds_lm)<sigma(df_lm,ds_rm) ) ds_rt=ds_rm;
else ds_lf=ds_lm;
}
double min_lm=sigma(df_lm,ds_lm);
ds_lf=0.0,ds_rt=1.0;
while ( ds_rt-ds_lf>eps )
{
ds_lm=ds_lf+(ds_rt-ds_lf)/3.0,ds_rm=ds_rt-(ds_rt-ds_lf)/3.0;
if ( sigma(df_rm,ds_lm)<sigma(df_rm,ds_rm) ) ds_rt=ds_rm;
else ds_lf=ds_lm;
}
double min_rm=sigma(df_rm,ds_lm);
if ( min_lm<min_rm ) df_rt=df_rm;
else df_lf=df_lm;
}
print(sigma(df_lm,ds_lm));
return 0;
}