Function
Problem Description
wls 有 n 個二次函數 Fi(x) = aix2 + bix + ci (1 ≤ i ≤ n).
現在他想在∑ni=1xi = m 且 x 為正整數的條件下求∑ni=1Fi(xi)的最小值。
請求出這個最小值。
Input
第一行兩個正整數 n, m。
下面 n 行,每行三個整數 a, b, c 分別代表二次函數的二次項, 一次項,常數項系數。
1 ≤ n ≤ m ≤ 100, 000
1 ≤ a ≤ 1, 000
−1, 000 ≤ b, c ≤ 1, 000
Output
一行一個整數表示答案。
Sample Input
2 3
1 1 1
2 2 2
Sample Output
13
解題思路:
利用結構體維護每個函數f(x+1)-f(x)的差值,一開始將所有函數x置為1,貪心,優先取差值小的函數,x+1並更新差值重新放入優先隊列中直至用完m-n個數為止
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e6 + 7;
const ll MAXM = 1e3 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
struct node
{
ll a, b, c;
ll mark;
ll x;
bool operator<(const node &t) const
{
return mark > t.mark;
}
};
int main()
{
ll n, m;
while (~scanf("%lld%lld", &n, &m))
{
priority_queue<node> pq;
ll ans = 0;
for (int i = 0; i < n; i++)
{
node t;
scanf("%lld%lld%lld", &t.a, &t.b, &t.c);
ans += t.a + t.b + t.c;
t.x = 1;
t.mark = t.a * (2 * t.x + 1) + t.b;
pq.push(t);
}
for (int i = 0; i < m - n; i++)
{
node temp = pq.top();
pq.pop();
temp.x++;
temp.mark = temp.a * (2 * temp.x + 1) + temp.b;
pq.push(temp);
ans += temp.a * (2 * temp.x - 1) + temp.b;
}
printf("%lld\n", ans);
}
return 0;
}
Clock
Problem Description
wls 有一個鍾表,當前鍾表指向了某一個時間。
又有一些很重要的時刻,wls 想要在鍾表上復現這些時間(並不需要依次復現)。我們可以順時針轉動秒針,也可以逆時針轉動秒針,分針和時針都會隨着秒針按規則轉動,wls 想知道秒針至少轉動多少角度可以使每個時刻至少都會被訪問一次。
注意,時鍾上的一種時針分針秒針的組合,可以代表兩個不同的時間。
Input
第一行一個整數 n 代表有多少個時刻要訪問。
第二行三個整數 h,m,s 分別代表當前時刻的時分秒。
最后n行每一行三個整數 hi,mi,si 代表每個要訪問的時刻的時分秒。
1 ≤ n ≤ 86, 400
0 ≤ h, hi < 24
0 ≤ m, mi, s, si < 60
Output
輸出一行一個數代表秒鍾轉的角度,答案保留兩位小數。
Sample Input
1
0 1 0
0 1 1
Sample Output
6.00
解題思路:
總共有一直順時針轉,一直逆時針轉,先逆時針后順時針,先順時針后逆時針轉四種情況,直接模擬
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e6 + 7;
const ll MAXM = 1e3 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
int main()
{
int n, h, m, s;
int h1, m1, s1;
int ans = 0;
int suma = 12 * 3600;
while (~scanf("%d", &n))
{
scanf("%d%d%d", &h, &m, &s);
h %= 12;
int start = h * 3600 + m * 60 + s;
ans = 0;
int ed1 = start, ed2 = start; //倒回去最接近0,順下去最接近12
int st1 = 0, st2 = suma; //倒回去最接近起點,順下去最接近起點
for (int i = 0; i < n; i++)
{
scanf("%d%d%d", &h1, &m1, &s1);
h1 %= 12;
int sum = h1 * 3600 + 60 * m1 + s1;
ed2 = max(ed2, sum);
ed1 = min(ed1, sum);
if (sum < start)
st1 = max(st1, sum);
else if (sum > start)
st2 = min(sum, st2);
}
ans = min(min(suma - (start - st1), suma - (st2 - start)), min(start - ed1 + ed2 - ed1, ed2 - start + ed2 - ed1));
ans *= 6;
printf("%d.00\n", ans);
}
return 0;
}