您的位置:首页 > 其它

2016 ACM青岛区域赛题解

2017-08-11 12:36 393 查看
A 水题,直接暴力模拟即可。

#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=40000;
typedef long long ll;

int main(int argc, char const *argv[])
{
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
ll ans=0,a,b;
for(int i=0;i<n;i++){
scanf("%lld %lld",&a,&b);
ans+=(a*b);
}
printf("%lld\n",ans);
}
return 0;
}


B 画风突然转变好多了呢!如果细细地想,应该是很难的,但是题目只要求一步之内啊,所以直接模拟就好了
<此处应有代码>

C题 :给定一个长度为L的木棒,每次可以截取最长位D的长度,当剩下长度<=d的时候截取结束,要求达到要求所需要的截取次数的期望。

计算概率,这题正统做法我不会,然后根据别人的提示log(2)=0.693147,然后找到了规律,就这还忽略了l<d的一种情况,2A

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn=40000;
typedef long long ll;
const double eps=1e-6;

int main(int argc, char const *argv[])
{
int T;
scanf("%d",&T);
while(T--){
double l,d;
scanf("%lf %lf",&l,&d);
if(l-d<eps){
printf("0.000000\n");
}
else{
double ans=log(l/d)+1;
printf("%.6f\n",ans);
}
}
return 0;
}


正统做法补上:点击打开链接

D Lucky Coins

题意:有n个种类的硬币,每i种硬币有num[i]个,掷硬币正面朝上的概率为p[i]。

现在对这n种硬币进行依次进行投掷,如果最后只剩下一种硬币,那么这种硬币就为Lucky Coins,问每一种硬币成为Lucky Coins的概率是多少。

思路的话十分简单,首先,我们先计算出到达第k步的时候硬币i死亡的概率 kill[i][j]=(1−p[i]j)num[i]

我们就可以计算出到达第i步之后i存活的概率 recv[i][j]=1−kill[i][j]

那么,我们就可以得到某一个硬币i成为lucky coins的概率 ans[i]=∑j=1max(recv[i][j]−recv[i][j+1)∗∏k=0,k≠inkill[k][j]

这个max是如何确定呢,我们知道所有的概率都在0.4-0.6之间,而总的硬币的个数在100000之内,我们就可以计算收敛的速度了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-6;
const int maxn=10005;
const int maxm=100005;

double kill[12][100000],p[12],live[12][100000],ans[15];
int num[12];

int main(int argc, char const *argv[])
{
int T;
scanf("%d",&T);
while(T--){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d %lf",&num[i],&p[i]);
}
memset(kill,0,sizeof(kill));
memset(live,0,sizeof(live));
memset(ans,0,sizeof(ans));
if(n==1){
printf("%.6f\n",1.0);
}
else{
for(int i=1;i<=n;i++){
double tmp=p[i];
for(int j=1;j<=100;j++){
kill[i][j]=pow(1-tmp,num[i]);
live[i][j]=1-kill[i][j];
tmp*=p[i];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=75;j++){
double tmp=1.0;
for(int k=1;k<=n;k++){
if(k!=i){
tmp*=kill[k][j];
}
}
ans[i]+=(live[i][j]-live[i][j+1])*tmp;//计算只在第j轮存活的概率
}
}
for(int i=1;i<=n;i++){
printf("%.6f%c",ans[i],i==n?'\n':' ');
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: