2020 年百度之星三

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<bits/stdc++.h>
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;i<n;i++)
        {
            scanf("%d %lf",&b[i],&c[i]);
            k[i]=1/(b[i]/(1-c[i])+1);
        }
        for(int i=0;i<n;i++)
        if(k[i]>Max)
        {
        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<p≤2),p 最多保留五位小数,表示 Alice 拿到的金币数目。

Output
对于每组数据,输出 Yes 表示需要交换,输出 No 表示不要交换。

Sample Input
1
1.00000
Sample Output
Yes

思路:
A拿到了 p(0<p<=1),那么B有2种情况:
情况一: 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<bits/stdc++.h>
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<j≤n 而且A[i]>A[j],则<A[i],A[j]> 这个有序对称为 A的一个逆序对。

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-2
m)*m+sum[m-1]
其中sum[i]为前i项和
简化一下就是 ans=2 * n * m - 2 * m * m - m
代码如下:

#include<bits/stdc++.h>
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<lowr-1时ans=lowr+1

代码如下:

下面展示一些 内联代码片

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,n,x,y;
int main()
{
	cin>>t;
	while(t--)
	{
		ll lowl=0,lowr=0;
		ll ans=0;
		cin>>n;
		while(n--)
		{
			cin>>x>>y;
			if(x==1)lowr=max(lowr,y);
		    else lowl=max(lowl,y);
		}
		if(lowl==0)ans=lowr+1;
		else if(lowr-1==lowl)ans=lowl+3;
	    else if(lowr-1>lowl)ans=lowr+1;
	    else ans=lowl+2;
	    cout<<ans<<endl;
	}
	return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值