信息学奥赛一本通 1979:【18NOIP普及组】龙虎斗 | 洛谷 P5016 [NOIP2018 普及组] 龙虎斗

【题目链接】

ybt 1979: 【18NOIP普及组】龙虎斗
洛谷 P5016 [NOIP2018 普及组] 龙虎斗

【题目考点】

1. long long类型使用

已知变量a, b是int类型的变量,且a * b的值会超出int类型可以表示的范围,如果写为:long long c = a * b;,c不会得到正确的结果。正确的写法为:long long c = (long long)a * b;
把一个变量强转为long long类型后,后面的运算就是两个long long类型的变量相乘,会得到正确的结果。例:

int a = 100000, b = 100000;
long long c = (long long)a * b;//此时c的值为10^10
2. 求绝对值

<stdlib.h>中有
int abs(int a);
long labs(long a);
但没有针对long long类型变量的求绝对值的函数,所以我们必须手动实现。

long long Abs(long long a)
{
    return a > 0 ? a : -a;
}

【解题思路】

  • 先把s1个兵添加上去,然后求龙虎双方的气势值。

  • 枚举每隔位置,尝试将s2个兵添加到这个位置,求出气势差值。将每次求出的气势差值比较,得到最小的气势差值,以及气势差值最小时,将s2个兵安排的位置。

  • 注意:观看数据范围,每个位置的工兵数最大为 1 0 9 10^9 109,共有 1 0 5 10^5 105个位置,加起来的气势和可以估算为 1 0 9 ⋅ 1 0 5 = 1 0 14 10^9 \cdot 10^5 = 10^{14} 109105=1014超出了int型变量可以表达的范围,所以对某些变量要用long long类型
    某些int型量间的计算,如s2 * (m - i),结果可能超出int型的范围,所以得先强转为long long类型后才能运算
    ,应写为:(long long)s2 * (m - i)

【题解代码】

解法1:分别求出龙方和虎方的气势
#include<bits/stdc++.h>
using namespace std;
#define N 100005
long long Abs(long long a)
{
    return a > 0 ? a : -a;
}
int a[N];//a[i]表示第i位置的工兵数
int main()
{
    int n, m, p1, s1, s2, p2;//p2:s2个兵放在p2位置时双方差值最小
    long long ql = 0, qh = 0, mn, delta;//ql:龙方气势 qh:虎方气势 mn:两方最小气势差值  delta:气势差值
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> a[i];
    cin >> m >> p1 >> s1 >> s2;
    a[p1] += s1;//天降神兵
    for(int i = 1; i < m; ++i)//统计当前龙方气势
        ql += (long long)a[i] * (m - i);
    for(int i = m + 1; i <= n; ++i)//统计当前虎方气势
        qh += (long long)a[i] * (i - m);
    mn = Abs(ql - qh);//双方气势差值最大也就是当前的差值,s2个工兵放下后,气势差值只能更小
    p2 = m;//s2个兵放在第m位置时,气势差值即为|ql - qh|
    for(int i = 1; i <= n; ++i)
    {
        if(i < m)
            delta = Abs(ql + (long long)s2 * (m - i) - qh);//向龙方i位置放s2个兵,龙方增加气势s2 * (m - i)。求此时龙虎双方的气势差值。
        else if(i > m)
            delta = Abs(qh + (long long)s2 * (i - m) - ql);//向虎方i位置放s2个兵,虎方增加气势s2 * (i - m)。求此时龙虎双方的气势差值。
        if(delta < mn)//求最小的delta,及delta最小时放兵的位置
        {
            mn = delta;
            p2 = i;
        }
    }
    cout << p2;
    return 0;
}
解法2:龙方气势是正数,虎方气势是负数

设置变量q表示双方总气势,q > 0表示龙方气势高,q < 0表示虎方气势高, ∣ q ∣ |q| q就是双方气势的差值

#include<bits/stdc++.h>
using namespace std;
#define N 100005
long long Abs(long long a)
{
    return a > 0 ? a : -a;
}
int a[N];//a[i]表示第i位置的工兵数
int main()
{
    int n, m, p1, s1, s2, p2;//p2:s2个兵放在p2位置时双方差值最小
    long long q = 0, mn, delta;//q:总气势,q > 0表示龙方气势高,q < 0表示虎方气势高 mn:两方最小气势差值  delta:气势差值
    cin >> n;
    for(int i = 1; i <= n; ++i)
        cin >> a[i];
    cin >> m >> p1 >> s1 >> s2;
    a[p1] += s1;//天降神兵
    for(int i = 1; i <= n; ++i)//统计总气势
        q += (long long)a[i] * (m - i);//龙方气势是正数,虎方气势是负数
    mn = Abs(q);//双方气势差值最大也就是当前的差值,s2个工兵放下后,气势差值只能更小
    p2 = m;//s2个兵放在第m位置时,气势差值即为|q|
    for(int i = 1; i <= n; ++i)
    {
        delta = Abs(q + (long long)s2 * (m - i));//向龙方i位置放s2个兵,总气势改变s2 * (m - i)。
        if(delta < mn)//求最小的delta,及delta最小时放兵的位置
        {
            mn = delta;
            p2 = i;
        }
    }
    cout << p2;
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值