1. 程式人生 > >題解 P2085 【最小函式值】

題解 P2085 【最小函式值】

題目描述

有n個函式,分別為F1,F2,...,Fn。定義Fi(x)=Aix^2+Bix+Ci (x∈N*)。給定這些Ai、Bi和Ci,請求出所有函式的所有函式值中最小的m個(如有重複的要輸出多個)。

輸入輸出格式

輸入格式:

輸入資料:第一行輸入兩個正整數n和m。以下n行每行三個正整數,其中第i行的三個數分別位Ai、Bi和Ci。Ai<=10,Bi<=100,Ci<=10 000。

輸出格式:

輸出資料:輸出將這n個函式所有可以生成的函式值排序後的前m個元素。這m個數應該輸出到一行,用空格隔開。

輸入輸出樣例

輸入樣例#1:

3 10
4 5 3
3 4 5
1 7 1

輸出樣例#1:

9 12 12 19 25 29 31 44 45 54

資料範圍

n, m <= 10000

主要思路:STL + 初中數學(實質是瞎搞)

STL就是用的優先佇列。

對於一個函式 \(f(x) = a x ^ {2} + b x + c\),我們會發現對稱軸為\(x = -\frac{b}{2a}\),所以函式\(f(x)\)\([1, +∞)\),根據題意\(x ∈N^{*}\),可知對於每個函式\(f(x)\)都是單調遞增的。

所以我們就可以對於每個函式,先取\(x = 1\),然後再當從堆中取出這個函式的\(x = 1\)時,把\(x = 2\)扔進堆中,,,

然而,此題資料正如第一篇題解體現的那樣,資料

所以,我們可以為所欲為!

我直接把所有函式的前10個值放進去,WA * 9

然後,我把函式的前100個值放進去,AC……

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define go(i, j, n, k) for(int i = j; i <= n; i += k)
inline int read(){
    int x = 0, f = 1; char ch = getchar();
    while(ch > '9' || ch < '0') { if(ch == '-') f = -f; ch = getchar(); }
    while(ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
#define abc a[i], b[i], c[i]
int a[mn], b[mn], c[mn];
inline int get_f(int x, int a, int b, int c) {
    return x * x * a + x * b + c;
}
priority_queue<int> q;
int n, m;

int main(){
    n = read(), m = read();
    go(i, 1, n, 1) {
        a[i] = read(), b[i] = read(), c[i] = read();
    }
    go(i, 1, n, 1) {
        go(j, 1, 100, 1) {
            q.push(-1 * get_f(j, abc));
        }
    }
    go(i, 1, m, 1) {
        printf("%d ", -1 * q.top());
        q.pop();
    }
    return 0;
}