CF524C:The Art of Dealing with ATM(打表 + 二分)

C. The Art of Dealing with ATM
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

ATMs of a well-known bank of a small country are arranged so that they can not give any amount of money requested by the user. Due to the limited size of the bill dispenser (the device that is directly giving money from an ATM) and some peculiarities of the ATM structure, you can get at most k bills from it, and the bills may be of at most two distinct denominations.

For example, if a country uses bills with denominations 10501005001000 and 5000 burles, then at k = 20 such ATM can give sums 100 000 burles and 96 000 burles, but it cannot give sums 99 000 and 101 000 burles.

Let's suppose that the country uses bills of n distinct denominations, and the ATM that you are using has an unlimited number of bills of each type. You know that during the day you will need to withdraw a certain amount of cash q times. You know that when the ATM has multiple ways to give money, it chooses the one which requires the minimum number of bills, or displays an error message if it cannot be done. Determine the result of each of the q of requests for cash withdrawal.

Input

The first line contains two integers nk (1 ≤ n ≤ 50001 ≤ k ≤ 20).

The next line contains n space-separated integers ai (1 ≤ ai ≤ 107) — the denominations of the bills that are used in the country. Numbers ai follow in the strictly increasing order.

The next line contains integer q (1 ≤ q ≤ 20) — the number of requests for cash withdrawal that you will make.

The next q lines contain numbers xi (1 ≤ xi ≤ 2·108) — the sums of money in burles that you are going to withdraw from the ATM.

Output

For each request for cash withdrawal print on a single line the minimum number of bills it can be done, or print  - 1, if it is impossible to get the corresponding sum.

Examples
input
6 20
10 50 100 500 1000 5000
8
4200
100000
95000
96000
99000
10100
2015
9950
output
6
20
19
20
-1
3
-1
-1
input
5 2
1 2 3 5 8
8
1
3
5
7
9
11
13
15
output
1
1
1
2
2
2
2
-1

题意:n种面值钱,各有无限张,q个询问,判断能否用<=2种面值的钱,且<=k张,构成指定的总金额,若可以,输出最少的钱张数。

思路:留意到k值不大,可以枚举所有面值的钱各k张能得到多少金额,排序二分查找即可。

# include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <vector>
# define LL long long
# define INF 0x3f3f3f3f
using namespace std;
vector<int>a[21];
int main()
{
    int n, k, q, num, ans;
    while(~scanf("%d%d",&n,&k))
    {
        for(int i=1; i<=20; ++i)
            a[i].clear();
        for(int i=0; i<n; ++i)
        {
            scanf("%d",&num);
            for(int j=1; j<=k; ++j)
                a[j].push_back(j*num);
        }
        for(int i=1; i<=k; ++i)
            sort(a[i].begin(), a[i].end());
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d",&num);
            ans = INF;
            bool flag = false;
            for(int i=1; i<=k; ++i)
            {
                for(int j=0; j<a[i].size(); ++j)
                {
                    if(a[i][j] == num)
                    {
                        ans = min(ans, i);
                        flag = true;
                        break;
                    }
                    if(a[i][j] > num)
                        break;
                    for(int t=i; t<=k-i; ++t)
                    {
                        int pos = lower_bound(a[t].begin(), a[t].end(), num-a[i][j]) - a[t].begin();
                        if(pos < a[t].size() && a[t][pos] == num-a[i][j])
                            ans = min(ans, i+t);
                    }
                }
                if(flag)
                    break;
            }
            if(ans == INF)
            {
                puts("-1");
                continue;
            }
            else
                printf("%d\n",ans);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值