付账问题

付账问题

几个人一起出去吃饭是常有的事。
但在结帐的时候,常常会出现一些争执。
现在有 n 个人出去吃饭,他们总共消费了 S 元。
其中第 i 个人带了 ai 元。
幸运的是,所有人带的钱的总数是足够付账的,但现在问题来了:每个人分别要出多少钱呢?
为了公平起见,我们希望在总付钱量恰好为 S 的前提下,最后每个人付的钱的标准差最小。
这里我们约定,每个人支付的钱数可以是任意非负实数,即可以不是 1 分钱的整数倍。
你需要输出最小的标准差是多少。
标准差的介绍:标准差是多个数与它们平均数差值的平方平均数,一般用于刻画这些数之间的“偏差有多大”。
形式化地说,设第 i 个人付的钱为 bi 元,那么标准差为 :
在这里插入图片描述

输入格式
第一行包含两个整数 n、S;
第二行包含 n 个非负整数 a1, …, an。

输出格式
输出最小的标准差,四舍五入保留 4 位小数。

数据范围
1≤n≤5×105,
0≤ai,S≤109
输入样例1:

5 2333
666 666 666 666 666

输出样例1:

0.0000

输入样例2:

10 30
2 1 4 7 4 8 3 6 4 7

输出样例2:

0.7928

思路:贪心
代码:

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=500010;
int n;
double s;
double avg;
int m[N];

int main(){
    cin >> n >> s;
    double avg=s/n;
    for(int i=0;i<n;i++)
        scanf("%d",&m[i]);
    sort(m,m+n);
    double cnt=0.0;
    for(int i=0;i<n;i++){
        double cur=s/(n-i);
        if(cur>m[i])
            cur=m[i];
        cnt+=(cur-avg)*(cur-avg);
        s-=cur;
    }
    printf("%.4lf",sqrt(cnt/n));
    return 0;
}

### 蓝桥杯竞赛题目的多种解法与思路分析 #### 付账问题(贪心算法) 对于 AcWing 1235. 付账问题,该题目属于典型的贪心算法应用实例。此问题的核心在于通过合理分配金额来最小化最大支付额。具体实现上,先计算平均值并以此为基础调整每个人的付款数额,从而达到整体最优效果[^1]。 ```python def min_max_payment(payments, average): surplus = sum([max(0, p - average) for p in payments]) deficit = sum([min(0, p - average) for p in payments]) return max(abs(surplus), abs(deficit)) ``` #### N皇后问题(回溯 vs 动态规划) 关于经典的N皇后放置难题,在处理较大规模输入时单纯依靠暴力枚举效率低下。采用回溯方法能够有效减少不必要的尝试次数;而当棋盘尺寸固定且较小的情况下,则可考虑利用动态规划求得全局最优解路径[^2]。 ```cpp bool solveNQ(int col[], int row){ if (row >= n) { printSolution(col); return true; } bool res = false; for (int i=0; i<n && !res; ++i){ if (isSafe(i, row, col)){ col[row]=i; res = solveNQ(col, row+1) || res; col[row]=-1; } } return res; } ``` #### 差分数组的应用场景 差分技术主要用于解决区间修改操作频繁的数据结构设计挑战。通过对原始序列构建对应的增量表,可以在O(1)时间复杂度内完成单点更新以及查询任意子区间的累加和运算[^3]。 ```java public class DifferenceArray { private final int[] diff; public DifferenceArray(int[] nums) { assert nums.length > 0; this.diff = new int[nums.length]; // 构造差分类 diff[0] = nums[0]; for (int i = 1; i < nums.length; i++) { diff[i] = nums[i] - nums[i - 1]; } } /* 给闭区间 [left,right] 增加 val */ public void increment(int left, int right, int val) { diff[left] += val; if (right + 1 < diff.length) { diff[right + 1] -= val; } } /* 返回结果数组 */ public int[] result() { int[] res = new int[diff.length]; // 根据差分数组构造结果数组 res[0] = diff[0]; for (int i = 1; i < diff.length; i++) { res[i] = res[i - 1] + diff[i]; } return res; } } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值