HourRank 10:Accessory Collection

题目链接: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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
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;
}





你可能感兴趣的:(Hackerrank)