2020 年百度之星三
1001:
Problem Description
学皇来到了一个餐馆吃饭。他觉得这家餐馆很好吃,于是就想办个会员。
一共有 n 种会员充值卡套餐,假设学皇这餐饭的消费为 a 元,选择第 i 种套餐,需要充值b[i]∗a 的钱,这次吃饭可以打c[i]×10 折,由充值的钱支付(即这次吃饭只需要从充值金额中扣除a×c[i] 元)。以后用剩余的充值的钱吃饭不再打折。
请问学皇应该选择哪个套餐(必须选择恰好一个套餐),使得优惠的比例最大?
优惠比例的定义是把充的钱用完以后,(本来应该付的钱 - 实际付的钱) / 本来应该付的钱。在这个题目里,实际付的钱就是这次充值的花费。
Input
第一行一个整数test(1≤test≤100) 表示数据组数。
对于每组数据,第一行一个正整数n(1≤n≤100) 表示套餐的数目。
接下来 n 行,每行一个正整数b[i] (1≤n≤100)和一个小数 c[i] (0≤c[i]≤1),(c[i] 最多包含两位小数)。
Output
对于每组数据,输出一个五位小数表示最大的优惠比例。如果小数点后超过五位,四舍五入到五位。
Sample Input
1
2
2 0.5
3 0.1
Sample Output
0.23077
样例解释
对于第一种套餐,优惠比例为 0.5a / (2a + 0.5a) = 0.2;
对于第二种套餐,优惠比例为 0.9a / (3a + 0.9a) = 9 / 39;
思路:直接看样例解释
即求
(1-c [ i ] ) / ( b [ i ] + ( 1 - c [ i ] ) )
的最大值
代码如下:
#include
typedef long long ll;
using namespace std;
int t,n,b[110];
double c[110],k[110];
int main()
{
scanf("%d",&t);
while(t--)
{
int co;
double Max=-1;
memset(k,0,sizeof(k));
scanf("%d",&n);
for(int i=0;iMax)
{
co=i;
Max=k[i];
}
printf("%.5lf\n",k[co]);
}
return 0;
}
1002
题目:
Problem Description
Alice 和 Bob 在玩游戏。
桌面上有两堆金币,少的那堆有 x 个金币,多的那堆有 2x 个金币。
假设金币可以被无限细分。Alice 和 Bob 事先都不知道 xx 是几,但是他们都知道 x 是一个 (0,1] 之间均匀分布的随机实数。
Alice 会等概率的被分配到其中的一堆金币,Bob 会得到另一堆。xx 的值和两堆金币的分配是相互独立的。
拿到金币以后,Alice 会马上数清自己拿到多少金币。然后 Alice 可以选择是否和 Bob 那堆换。
给定 Alice 拿到的金币数目,请问 Alice 要不要交换,使得她期望能得到的金币数目更多?
如果交换期望得到的金币数目多于不交换期望得到的金币数目,输出交换,否则不交换。
Input
第一行一个正整数test (1≤test≤200000) 表示数据组数。
接下来每行一个小数p (0
Output
对于每组数据,输出 Yes 表示需要交换,输出 No 表示不要交换。
Sample Input
1
1.00000
Sample Output
Yes
思路:
A拿到了 p(0
情况一: A拿到的是多的那一堆,则B拿到的金币 k 在 ( 0 , p / 2 ]内,期望大于( 0 + p / 2)/2
情况二:A拿到的是少的那一堆,则B拿到的金币k在( 0,2 * p ]内,期望大于
( 0 + 2 * p ) / 2
所以期望大于 (5 * p / 4)
如果A拿到的金币 p ( p > 1 ),那么A拿到的就是多的那一堆,显而易见这种情况是不换的。
如果A拿到的金币小于等于1,那么只要p < = 5*p/4 就换。
求一下不等式得
0<=p<=1时换;p>1时不换
代码如下:
#include
typedef long long ll;
using namespace std;
int t;
double p;
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%lf",&p);
if(p>1)printf("No\n");
else printf("Yes\n");
}
return 0;
}
1003
题目
Problem Description
一开始有 n 个数,他们按1…n 的顺序排列,要求交换最多 m 对数字(同一个数字可以参与多次交换),使得逆序对数目最大。
对于一个序列 A,如果存在正整数 i,j 使得1≤i
Input
第一行一个正整数test (1≤test≤100000) 表示数据组数。
对于每组数据,一行两个整数n,m (1≤n≤1000000,0≤m≤1000000) 表示数字个数和最多可以交换的数字对数。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
6
1 1
2 0
2 1
3 1
4 1
4 2
Sample Output
0
0
1
3
5
6
思路
把最后一个换到第一个来,可以推出一个公式
如 n=8,m=3;
原序列 1 2 3 4 5 6 7 8
交换后 8 7 6 4 5 3 2 1
首先看8、7和6
发现后面的5个数都是比8、7和6小的,个数为5+4+3;
再看4和5发现后面3个数都比4和5小的, 个数为(8-2*3)3
再看3、2和1,个数为2+1
易得
ans=sum[n-1]-sum[n-m-1]+(n-2m)*m+sum[m-1]
其中sum[i]为前i项和
简化一下就是 ans=2 * n * m - 2 * m * m - m
代码如下:
#include
typedef long long ll;
using namespace std;
ll t,n,m;
int main()
{
scanf("%lld",&t);
while(t--)
{
ll ans=0;
scanf("%lld%lld",&n,&m);
if(n==1)
{
printf("0\n");
continue;
}
else if(n/2<=m)m=n/2;
ans=2*n*m-2*m*m-m;
printf("%lld\n",ans);
}
return 0;
}
1004
题目
Problem Description
Mr. Left 来到了一个路口,这个路口只能右转,并且都是两车道。
现在在南北向车道上有 n 辆车,他们都在线 x 南边,这些车想要通过这个路口,到东边去,具体地说,他们要开到线 y 东边。
一辆车一个时刻可以从东南西北中选一个方向移动一个位置,或者呆在原地不动。
同一时刻同一位置不能有超过一辆车。车不能开到路外面。
在任意时刻,所有车都同时移动。两辆相邻的车不能都移动到对方的格子上。在此基础上,只要所有车移动后不存在两辆车处于同一位置,移动就合法。
问最少要多少时间,这些车才可以都开到东边?
Input
第一行一个整数 test (1≤test≤10)。
对于每组数据,第一行一个整数 n (1≤n≤100000),表示车辆数目。
接下来 n 行,每行两个整数 x,y 表示车的位置,其中 x 表示车道 id( x=1 表示右车道,x=2 表示左车道),y (1≤y≤100000) 表示车在路口前第几个位置。
数据保证没有两辆车初始在同一位置。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
2
2
1 1
2 1
2
1 2
2 1
Sample Output
3
4
样例解释 代码如下: 下面展示一些
第一组
time 0
…
…
CC
…
time 1
…
CC…
…
…
time2
…
.CC.
…
…
time3
…
…CC
…
…
第二组
time 0
…
…
C.
.C
time 1
…
C…
.C
…
time2
C…
.C…
…
…
time3
.C…
…C.
…
…
time4
…C.
…C
…
…
思路
只需要左路和右路最下面的车
记lowr为右路最下的位置,lowl为左路最下的位置
分3种情况
第一种:只有一边有车
左边有车 ans=lowl+2
右边有车ans=lowr+1;
第二种:当lowl==lowr-1时右路的车会影响左路的车
ans=lowl+3
第三种:两路的车互不影响
当lowl>lowr-1时ans=lowl+2
当lowl内联代码片
。#include