蓝桥杯:169、乘积最大、174、付账问题(C++)

目录

乘积最大

题目描述

输入输出样例

实现代码:

原理思路:

付账问题

题目描述

输入输出样例

实现代码:

原理思路:


        严格的证明没有给出,只有解题思路,感兴趣可以去网上查证明,贪心问题证明还是很难的。

乘积最大

题目描述

输入描述

输出描述

输出一个整数,表示答案。

输入输出样例

输入

5 3
-100000
-10000
2
100000
10000

输出

999100009

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

实现代码:

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N =100010;
const int mod = 1000000009;

typedef long long LL;

int n, k;
int a[N];

int main()
{
    cin >> n >> k;
    for (int i = 0 ; i < n; i++) cin >> a[i];
    
    sort(a, a + n);
    
    int i = 0, j = n - 1;//左右指针
    LL res = 1;
    int flag = 1;//看最后一个数是否为负数
    
    //是奇数,就先把最后一个选了,然后就变为选偶数问题。
    if (k % 2)
    {
        res = a[j];
        if (res < 0) flag = -1;
        k--;
        j--;
    }
    
    //成对的选择,左右两对,看谁大
    while(k)
    {
        LL l = (LL)a[i] * a[i + 1];
        LL r = (LL)a[j] * a[j - 1];
        //选左边两对
        if (l * flag > r * flag)//若都是负数就乘-1,选小的,这样总值就负的少一点
        {
            i += 2;//指针移动
            res = l % mod * res % mod;
        }
        else
        {
            j -= 2;//指针移动
            res = r % mod * res % mod;
        }
        k -= 2;
    }
    printf("%lld", res);
    
}

原理思路:

        主要分为两种情况,一种是k为奇数,一种是为偶数。

        先排序。

        在k为奇数时,我们先选择最后一个元素,这样就转化为了k为偶数问题。这里注意,判断一下最后一个元素是不是负数,若是负数,就记录一下sign = -1,因为如果最后一个是负数,其他全部数字也是负数,我们不可能找出最终结果为正数的答案,后面的选择就会发生变化。

        然后我们分别定义两个指针,一个指向头,一个指向尾,求出头两对的乘积和尾两对的乘积,然后乘以sign,上面说了若都是负数的话,我们就要选择乘积最小的,这样负的越小,值反而越大。若sign是1,那么就正常的比较出两个中的最大值(一般情况),然后根据选择来移动指针,同时k也减小2。

        当k为0时就代表选择完毕,记得定义res为long long类型。

付账问题

题目描述

输入描述

输出描述

输入输出样例

输入

5 2333
666 666 666 666 666

输出

0.0000

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

实现代码:

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N = 500010;

int n;
long double s;
int a[N];

int main()
{
    cin >> n;
    cin >> s;
    for (int i = 0; i < n; i++) scanf("%d", &a[i]);
    
    sort(a, a + n);//记得sort
    
    long double res = 0;
    long double avg = s * 1.0 / n;//总的平均值
    for (int i = 0; i < n; i++)
    {
        
        long double cur = s / (n - i);//当前需要的平均值(当前需要交的钱), 除的是 n - i ,细节
        //小于的话有多少给多少
        if (a[i] < cur) cur = a[i];
        //大于的话,就给当前的平均值就行
        s -= cur;//总的需要交的钱减少了
        res += (cur - avg) * (cur - avg);
    }
    
    printf("%.4llf", sqrt(res / n));//标准差
    return 0 ;

}

原理思路:

        先排序。 

        当一个人钱不够当前平均值时,就有多少拿多少。

        当一个人钱够当前平均值时,就拿出当前平均值即可。

        当前的平均值根据差的钱和人数,需要不断的更新。(可以根据注释看)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Cosmoshhhyyy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值