今天洛谷比赛的题。(打不了CF只好做洛谷比赛,用空气树这个号打的)
A的非常莫名。
题目链接:https://www.luogu.com.cn/problem/P2051
首先要能计算出期望值,我完全没有学过期望,只好乱猜。
期望值应该是要按最坏的打算。
要求一次性成功,否则重来。
那么期望第一个任务做的次数便是所有概率乘积的倒数。
那么第二个任务呢?就是\(2\)~\(n\)所有概率乘积的倒数。
以此类推。也就是后缀了。
而我当时完全想错了。
但是直觉认为是贪心,排序。
于是推了个这样的式子。(根据题,\(p[i]都*了10000\))
\(xx.x\)表示完成代价,\(xx.y\)表示期望值\(p[i]\),\(10000/xx.y\)也就是单独一个任务的期望次数
排序的式子(也就是把xx放在yy前的要求):
\(10000 * xx.x/xx.y+10000 * 10000 * yy.x/xx.y/yy.y<10000 * yy.x/yy.y+10000 * 10000 * xx.x/yy.y/xx.y;\)
\(-->xx.x * yy.y+10000 * yy.x<yy.x * xx.y+10000 * xx.x\)
然后\(WA\)了。
于是我开始乱猜,把\(<改>\)就过了!!惊讶万分。
什么原因?
显然,我当时的思路是按照前缀,而实际是按期望值的后缀。也就是我排出的是反着的。
式子应该是:
\(10000 * 10000 * xx.x/xx.y/yy.y+10000 * yy.x/yy.y<10000 * 10000 * yy.x/yy.y/xx.x+10000 * xx.x/xx.y\)
\(-->10000 * xx.x+yy.x * xx.y<10000 * yy.x+xx.x * yy.y\)
所以,我当时刚好相反了(想成了前缀,也就是把序列颠倒),把\(<改>\)就过了。
附上当时的代码。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define int long long
#define re register int
inline int read(){
int x=0,ff=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')ff=-1;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return x*ff;
}
struct tt{
int x,y,id;
bool friend operator <(tt xx,tt yy){
return xx.x*yy.y+10000*yy.x>yy.x*xx.y+10000*xx.x;
}
}a[500005];
int n;
inline void debug(int &x){cout<<x<<endl;}
signed main(){
n=read();bool is=1;
for(re i=1;i<=n;i++)a[i].x=read(),a[i].id=i;
for(re i=1;i<=n;i++)a[i].y=read(),is&=a[i].y>0;
if(!is){puts("Impossible");return 0;}
sort(a+1,a+n+1);
for(re i=1;i<=n;i++)printf("%lld ",a[i].id);
puts("");
return 0;
}
所以这就算我自己摸索出期望了?