题解:洛谷 P2965 The Grand Farm-off

【题目来源】

洛谷:P2965 [USACO09NOV] The Grand Farm-off S - 洛谷

【题目描述】

Farmer John owns \(3*N (1 <= N <= 500,000)\) cows surprisingly numbered \(0..3*N-1\), each of which has some associated integer weight \(W_i (1 <= W_i <= d)\). He is entering the Grand Farm-off, a farming competition where he shows off his cows to the greater agricultural community.

This competition allows him to enter a group of \(N\) cows. He has given each of his cows a utility rating \(U_i (1 <= U_i <= h)\), whichrepresents the usefulness he thinks that a particular cow will have in the competition, and he wants his selection of cows to have the maximal sum of utility.

There might be multiple sets of \(N\) cows that attain the maximum utility sum. FJ is afraid the competition may impose a total weight limit on the cows in the competition, so a secondary priority is to bring lighter weight competition cows.

Help FJ find a set of \(N\) cows with minimum possible total weight among the sets of \(N\) cows that maximize the utility, and print the remainder when this total weight is divided by \(M (10,000,000 <= M <= 1,000,000,000)\).

Note: to make the input phase faster, FJ has derived polynomials which will generate the weights and utility values for each cow. For each cow \(0 <= i < 3*N\),

\(W_i=(a\times i^5+b\times i^2+c)\mod d\)

\(U_i=(e\times i^5+f\times i^3+g)\mod h\)

\((0\le a,b,c,d,e,f,g,h\le 10^9)\)

The formulae do sometimes generate duplicate numbers; your algorithm should handle this properly.

农夫约翰有 \(3*N (1 <= N <= 500,000)\) 头牛,编号依次为 \(0..3*N-1\),每头牛都有一个整数值的体 重。约翰准备参加农场技艺大赛,向广大的农业社区展示他的奶牛。
大赛规则允许约翰带 \(N\) 头牛参赛。约翰给每头牛赋予了一个“有用度” \(U_i\),它表 示了某头牛在比赛中的有用程度。约翰希望他选出的奶牛的有用度之和最大。

有可能选出很多组的 \(N\) 头牛都能达到有用度最大和。约翰害怕选出的 \(N\) 头牛的总重量会给大赛 带来震撼,所以,要考虑优先选择体重轻的奶牛。

帮助约翰选出 \(N\) 头总重量最轻,并且有用度之和最大的奶牛。输出体重模 \(M\) 后的余数。

注意:为了使输入更快,约翰使用了一个多项式来生成每头牛的体重和有用度。对每头牛/,体重和有用度的计算公式为:

\(W_i=(a\times i^5+b\times i^2+c)\mod d\)

\(U_i=(e\times i^5+f\times i^3+g)\mod h\)

\((0\le a,b,c,d,e,f,g,h\le 10^9)\)

【输入】

* Line 1: Ten space-separated integers: N, a, b, c, d, e, f, g, h, and M

【输出】

* Line 1: A single integer representing the lowest sum of the weights of the N cows with the highest net utility.

【输入样例】

2 0 1 5 55555555 0 1 0 55555555 55555555

【输出样例】

51

【核心思想】

  1. 问题分析:给定 \(3N\) 头奶牛,每头牛有体重 \(W_i\) 和有用度 \(U_i\)(由多项式公式生成)。需要选出 \(N\) 头牛,使得有用度之和最大;在有多个最优解时,选择总重量最小的方案,输出总重量模 \(M\) 的结果。这是一个排序贪心问题,关键在于按有用度降序排序后取前 \(N\) 头,有用度相同时按体重升序排序确保优先选轻的。

  2. 算法选择

    • 多项式生成数据:按给定公式计算每头牛的 \(W_i\)\(U_i\)
    • 自定义排序:按有用度 \(U_i\) 降序排序,\(U_i\) 相同时按体重 \(W_i\) 升序排序
    • 贪心选取:取排序后的前 \(N\) 头牛,累加体重后模 \(M\)
  3. 关键步骤

    • 读取输入\(N, a, b, c, d, e, f, g, h, M\)
    • 生成数据\(i\)\(0\)\(3N-1\)):
      • \(W_i = (a \cdot i^5 + b \cdot i^2 + c) \% d\)
      • \(U_i = (e \cdot i^5 + f \cdot i^3 + g) \% h\)
    • 自定义排序cmp 函数按 \(U_i\) 降序,\(U_i\) 相同时按 \(W_i\) 升序
    • 累加答案:取前 \(N\) 头牛,\(sumw = \sum_{i=0}^{N-1} W_i \% M\)
    • 输出 \(sumw\)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(3N \log(3N))\),生成数据 \(O(3N)\),排序 \(O(3N \log(3N))\)
    • 空间复杂度:\(O(3N)\),存储 \(3N\) 头牛的信息
  5. 排序贪心的核心思想

    • 字典序最优:按 \((U_i \text{ 降序}, W_i \text{ 升序})\) 排序,确保在有用度最大的前提下,优先选取体重更轻的牛
    • 多项式取模防溢出:计算过程中每一步都取模,防止 \(i^5\) 导致 \(64\) 位整数溢出
    • \(N\) 即最优:排序后前 \(N\) 个元素必然构成有用度最大且总重最小的最优解,无需复杂搜索
    • 适用于"双关键字排序 + 前缀选取"类问题,核心是通过排序实现字典序最优选择

【解题思路】

【算法标签】

普及- #其他排序

【代码详解】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, a, b, c, d, e, f, g, h, m;
struct node {
    ll w, u;
}p[1500005];
bool cmp (node x, node y)
{
    if (x.u==y.u) return x.w<y.w;
    return x.u>y.u;
}
int main()
{
    cin >> n >> a >> b >> c >> d >> e >> f >> g >> h >> m;
    for (int i=0; i<3*n; i++) {  // 按照题目描述计算每头牛的重量和有用度
        p[i].w = (a%d*i%d*i%d*i%d*i%d*i%d + (b%d*i%d*i%d+c%d)%d)%d;  // 需要把mod拆到每个数字中
        p[i].u = (e%h*i%h*i%h*i%h*i%h*i%h + (f%h*i%h*i%h*i%h+g%h)%h)%h;
    }
    sort(p, p+3*n, cmp);  // 按照有用度从大到小排序
    ll sumw=0;
    for (int i=0; i<n; i++) {  // 计算前n个奶牛的重量(默认前n个奶牛的有用度之和最大)
        sumw = (sumw+p[i].w)%m;
    }
    cout << sumw << endl;  // 输出
    return 0;
}

【运行结果】

2 0 1 5 55555555 0 1 0 55555555 55555555
51
posted @ 2026-08-28 15:56  团爸讲算法  阅读(3)  评论(0)    收藏  举报