[Google Code Jam 2017] Round 2 problem A

problem description:
You are the public relations manager for a chocolate manufacturer. Unfortunately, the company’s image has suffered because customers think the owner is cheap and miserly. You hope to undo that impression by offering a free factory tour and chocolate tasting.

Soon after starting the new project, you realized that the company owner’s reputation is well-deserved: he only agreed to give away free chocolate if you would minimize the cost. The chocolate to be given away comes in packs of P pieces. You would like to open new packs for each tour group, but the owner insists that if there are leftover pieces from one group, they must be used with the next tour group before opening up any new packs.

For instance, suppose that each pack contains P=3 pieces, and that a tour group with 5 people comes. You will open two packs to give one piece to each person, and you will have one piece left over. Suppose that after that, another tour group with 6 people comes. They will receive the leftover piece, and then you will open two more packs to finish giving them their samples, and so you will have one piece left over again. If two groups with 4 people each come right after, the first of those will get the leftover piece plus a full pack, and the last 4 person group will get their pieces from two newly opened packs. Notice that you cannot open new packs until all leftovers have been used up, even if you plan on using all of the newly opened pack immediately.

In the example above, 2 out of the 4 groups (the first and last groups) got all of their chocolate from freshly opened packs. The other 2 groups got some fresh chocolate and some leftovers. You know that giving out leftovers is not the best way to undo the owner’s miserly image, but you had to accept this system in order to get your cheap boss to agree to the project. Despite the unfavorable context, you are committed to doing a good job.

You have requests from N groups, and each group has specified the number of people that will come into the factory. Groups will come in one at a time. You want to bring them in in an order that maximizes the number of groups that get only fresh chocolate and no leftovers. You cannot reject groups, nor have a group get chocolate more than once, and you need to give exactly one piece to each person in each group.

In the example above, if instead of 5, 6, 4, 4, the order were 4, 5, 6, 4, a total of 3 groups (all but the 5 person group) would get only fresh chocolate. For that set of groups, it is not possible to do better, as no arrangement would cause all groups to get only fresh chocolate.

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case consists of two lines. The first line contains two integers N, the number of groups coming for a tour, and P, the number of pieces of chocolate per pack. The second line contains N integers G1, G2, …, GN, the number of people in each of the groups.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the number of groups that will receive only fresh chocolate if you bring them in in an order that maximizes that number.

Limits

1 ≤ T ≤ 100.
1 ≤ N ≤ 100.
1 ≤ Gi ≤ 100, for all i.
Small dataset

2 ≤ P ≤ 3.
Large dataset

2 ≤ P ≤ 4.
Sample

Input  
3
4 3
4 5 6 4
4 2
4 5 6 4
3 3
1 1 1

Output 
Case #1: 3
Case #2: 4
Case #3: 1

Sample Case #1 is the one explained in the statement. Besides the possible optimal order given above, other orders like 6, 5, 4, 4 also maximize the number of groups with only fresh chocolate, although the groups that get the fresh chocolate are not necesarily the same. Notice that we only care about the number of groups that get the best experience, not the total number of people in them.

In Sample Case #2, the groups are the same as in Case #1, but the packs contain two pieces each. In this case, several ways of ordering them — for instance, 4, 4, 6, 5 — make all groups get only fresh chocolate.

In Sample Case #3, all groups are single individuals, and they will all eat from the same pack. Of course, only the first one to come in is going to get a freshly opened pack.
题目大意:
有N个组的人要来参观工厂,工厂提供每包 P个巧克力若干包。每个组的人数不一,一个人只得一块巧克力。每包剩下的巧克力必须分发完,才能打开下一包。新打开的巧克力是新鲜巧克力,剩下的不新鲜。一个组的人每人都是吃到新鲜巧克力,才算这个组吃到了新鲜巧克力。为了使吃到新鲜巧克力的组数最大,可以有不同的参观顺序。不用求这个顺序,求能够使得最大多少组人能吃到新鲜巧克力?

解题思路:
根据pack的容量来分析,P可以为2,3,4这三种情况:

  • 当p为2,把每个组的人数对2求余,余数为一的两个结合,这样的每一对中有一个组的人可以全部吃到新鲜的巧克力;余数为零的每个组都可以吃到新鲜巧克力;如果多出一个余数为1的组不能配对,这个组的人也能全吃新鲜巧克力。

  • 当p为3,把每个组的人数对3求余,余数为一和余数为二的,一比一配对,这样的每一对中有一个组的人可以全部吃到新鲜巧克力;余数为零的每个组都可以吃到新鲜巧克力;剩余的组分为两种情况:一是剩余余数为一的组,二是剩余余数为二的组。不管是剩余余数为几的组,将这个组数再对3求余,商数为可以吃到新鲜巧克力的组数,如果余数不为0,则还有一组人也能吃到新鲜巧克力。

  • 当p为4,同理,把每个组的人数对4求余,余数为1,2,3。首先将余数为1和为3的配对,2和2配对,这样的每一对有一组可以全部吃到新鲜巧克力。如果余2的组数最后多了一组无法配对,记住这组。待1&3的配对结束后,将剩余余1或者余3的组数对3再求商求余,这个商数是可以吃到新鲜巧克力的组数,余数再分为>=2
    以及<2的情况。代码里很清楚了。

时空复杂度均为O(n)

Python代码:

#!/usr/bin/python
# -*- coding: utf-8 -*-

def mostGroup(n, p, pn):
    if p == 1 or n == 1:#如果只有一个组,肯定吃新鲜的
        return n
    count = 0#记录能吃到新鲜巧克力的组数
    res = []
    for i in pn:
        t = i % p #这里的i是每个组的人数
        res.append(t)#这里的t是每组人数对每包巧克力数目求余
    count = res.count(0)#余数为0的每组都可以吃到新鲜巧克力

    if p == 2:#如果每包2块巧克力
        count += res.count(1) / 2
        if res.count(1) % 2 == 1:
            count += 1

    if p == 3:#如果每包3块巧克力
        a = res.count(1)
        b = res.count(2)
        if a > b:
            count += b + (a - b) / 3
            if((a - b) % 3 > 0):
                count += 1
        if a == b:
            count += a
        if b > a:
            count += a + (b - a) / 3
            if ((b - a) % 3 > 0):
                count += 1

    if p == 4:#如果每包4块巧克力
        count1 = res.count(1)
        count2 = res.count(2)
        count3 = res.count(3)
        left2 = count2 % 2
        m = min(count1, count3)
        left1or3 = abs(count1 - count3)
        count += count2 / 2 + m + left1or3 / 4
        left1or3 %= 4
        if left2 == 1:
            if left1or3 <= 2:
                count += 1
            elif left1or3 > 2:
                count += 2
        elif left2 == 0:
            if left1or3 > 0 :
                count += 1

    return count


# f = open('A-small-practice.in', 'r')
f = open('A-large-practice.in', 'r')
t = int(f.readline())
# f1 = open('A-small-out19.txt', 'a')#correct
f1 = open('A-large-out10.txt', 'a')#correct
for i in range(1, t + 1):
    ls = [int(s) for s in f.readline().split()]
    n = ls[0]
    p = ls[1]
    pn = [int(s) for s in f.readline().split()]
    out = mostGroup(n, p, pn)
    f1.write('Case #{}: {}'.format(i, out))
    f1.write('\n')
f1.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值