重庆师范大学第一届ACM选拔赛(公开赛)G-团日活动

一、G-团日活动

题目链接戳这里↓.

题目描述
华华和班里的同学共N人一起去校外进行团日活动。到了晚上回家的时候,遇到一处独木桥要过,为了安全起见,华华提议一次只让两名同学过独木桥,
已知队伍中n名女生过桥都比较快,单独过桥只需要1分钟。m名男生因为体重较重,过桥的时间比较慢,
每名男生单独沟过桥分别需要1,2,3,4……分钟的时间来过桥。
当两个人同时过桥时,他们的过桥时间为较慢的那一名同学所需要的时间。

问,所有同学都过完独木桥所需要的最短时间是多少。

输入描述:
多组输入,第一行输入数据组的数目T(T<=1000)
第二行输入团队总人数N,和男生的人数n
(N<=1e9,m<N,n<N,数据保证团队中至少有1名男生或者1名女生)

输出描述:
每一行输出所有人过桥所需要的最短总时间。

示例1
输入

4
10
5
20
16
31
15
41
20

输出

11
74
72
121

示例2
输入

1
1000000000
999999998

输出

249999999500000001

二、解题思路:

读完题后,根据蓝色字体的两句话可知道解题的大致思路:

2.1思路

男生m个人的各过桥时间是1~m依次递增的,且两个人过桥时间取长的那段,所以两人过桥时应优先选择两个过桥时间最长的男生
女生过桥都是1分钟,所以也应两两一队过桥。

2.2考虑奇偶

此时再考虑各自人数奇偶之分,例如若男生人数是奇数,则必定剩下一个过桥时间最短的(1min),可以有两个思路:
①将1min男生移去女生队伍,当成男生-1&&女生+1
②将一个女生移入男生队伍配对,男生+1&&女生-1(推荐)

2.2.1奇偶情况举例说明

下面举四种奇偶情况作为说明:

tip:min_t表示最短时间,算式中蓝色为男生时间,橘色为女生时间。

  1. 女生人数n偶,男生人数m偶
    m = 4 : :1 2 3 4
    n= 2: 1 1
    min_t = 4+2+ 2/2=7
    (男生中两两配对,则应4、3一队,min_t+=4, 2、1一队,min_t+=2;
    女生亦两两配对,直接用人数/2即可。)

  2. 女生人数n奇,男生人数m奇
    m = 5:1 2 3 4 5
    n = 7 :1 1 1 1 1 1 1
    min_t = 1+5+3+ +7/2=12
    (男生:5、4一队,3、2一队,剩1,这时可假设将一个女生移入男生队列配对,一男一女过桥时间为1,男生时间算式就可为5+3+1;,
    int除法向下取整,故移走一个女生后,女生时间仍为7/2=3)

  3. 女生人数n偶,男生人数m奇
    m = 5: 1 2 3 4 5
    n =4 : 1 1 1 1
    min_t = 1+5+3+ +4/2= 11
    (男生情况跟第二种一样,剩一个1min男生,移入一个女生后男生时间为5+3+1;
    此时女生人数变为奇数3,两两配对的话会剩一个女生,需要一个人单独走(题目并没有说这种情况),女生时间也扔可用n/2=2=1+1)
    .

  4. 女生人数n奇,男生人数m偶
    m = 4: 1 2 3 4
    n = 5:1 1 1 1 1
    min_t =4+2+ (5+1)/2 =9
    (男生正好可配对完,时间为4+2;
    女生为奇数,这时要注意,两两配对会剩一个,需(n+1)/2才可得到正确的时间,或者n/2向上取整也可。)

题目中的样例也可以用这种方法来自己试验一下。

2.2.4奇偶结论

男生人数
m=偶数时,时间求和为2+4+6+8+……+m
m=奇数时,时间求和为1+3+5+7+……+m

女生人数
只有当m为偶数,n为奇数时,求和才为(n+1)/2
其余情况皆为n/2

2.3解题公式总结

min_t是分两部来求的,一部分是男生过桥时间,一部分女生过桥时间,男生过桥时间是总和其实就是一个等差数列求和的结果.
等差数列求和公式为在这里插入图片描述

  1. 男生人数m为偶:2+4+6+8+……+m,
    a1=2,项数N(区分女生人数)为m/2,d为2。
    Sn = m/2× 2 + (m/2)×(m/2-1)/2×2
    化简后Sn = (m/2)*(m/2+1)

  2. 男生人数m为奇:1+3+5+7+……+m,
    a1=1,项数N为(m+1)/2,d为2。
    Sn = (m+1)/2+(m+1)/2×((m+1)/2-1)/2×2
    化简后Sn = pow(m+1,2)/4

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
  int T;
  cin >> T;
  ll N, n, m;
  while (T--) {
    cin >> N >> m;
    n = N-m;//女生人数
    ll sum = 0, sn = 0;
    if (m % 2 == 0)//男生人数为偶数
      sn = (m/2)*(m/2+1); //m/2*2+(m/2)*(m/2-1)/2*2,因a1=2
    else//男生人数为奇数
      sn = pow(m+1,2)/4;  //(m+1)/2+(m+1)/2*((m+1)/2-1)/2*2
    sum = sum + sn + n/2;//男生时间+女生时间
    //m偶n奇情况女生人数要+1
    if (m%2==0 && n%2==1) {
      sum++;
    }
    cout << sum << endl;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你脸上有BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值