題目鏈接:https://www.hackerrank.com/contests/hourrank-10/challenges/accessory-collection
題意是1到A,A種物品,第i種物品價值爲i,你要買L件,要求滿足的條件是,買的L件物品中,任意挑選N件,其種類至少要有D種。問物品的總價值最大是多少。
做的時候很懵。。。貪了一下,只過了樣例。
經過鳥神的翻譯之後,題意可以簡化如下對於1<=i<=A,要構造一個數組,使得sum a[i] = L,然後b是a排好序之後,b的最大D-1個元素之和小於N。
接下來只好翻譯一下題解。。。
因爲最終的結果a肯定是一個非遞減數列,考慮最後d-1個元素之和,設爲S,這個S一定不能超過N,因爲超過的話,那麼選取這N個元素,種類就小於D了。然後還希望最終結果最大,所以S必爲N-1。
假設最後d-1個元素爲X,之後的我們再分配,那麼最後d-1個元素還有N-1-(d-1)*X沒有分配,這些爲了取最大值,分給A這個元素上了。
之後,同樣的,爲了取最大值,a又是一個非遞減數列,所以X一直賦值過去,賦到取不到爲止,數量爲B個,然後把剩下的給A-B-1。
E = N - 1 - X*(D - 1);
M = L - X - E;
B = M / X;
最終,枚舉X,取最大值。
代碼:
//#pragma comment(linker, "/STACK:102400000,102400000")
#pragma warning(disable:4996)
#include <fstream>
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <ctime>
#include <list>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define eps 1e-10
#define LL_INF 0x3fffffffffffffff
#define INF 0x3f3f3f3f
#define mem(a, b) memset(a, b, sizeof(a))
#define pper(i,n,m) for(int i = n;i >= m; i--)
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))
#define mp make_pair
#define ff first
#define ss second
#define pb push_back
const int maxn = 205;
const ll mod = 23333333;
const double PI = acos(-1.0);
ll L, A, N, D;
void solve()
{
scanf("%lld%lld%lld%lld", &L, &A, &N, &D);
if (A < D)
{
puts("SAD");
return;
}
ll res = 0;
ll X, M, B, E, Y;
for (X = 1; X <= L; X++)
{
ll r = 0;
E = N - 1 - X*(D - 1);
if (E < 0)
break;
r += (X + E)*A;
M = L - X - E;
if (M < 0)
{
continue;
}
B = M / X;
r += X*(2 * A - B - 1)*B / 2;
Y = M - B*X;
if (A - B - 1 < 0)
{
continue;
}
if (A - B - 1 == 0 && Y)
{
continue;
}
r += (A - B - 1)*Y;
res = max(res, r);
}
if (res == 0)
{
puts("SAD");
}
else
{
printf("%lld\n", res);
}
}
int main()
{
int t;
sa(t);
while (t--)
{
solve();
}
return 0;
}