“山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛(正式赛)K coins

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

Alice has 4 types of coins. The values of the 4 types of coins are 2,3,17,19respectively. Each kind of coin has an unlimited supply.

Bob also has 4 types of coins. The values of the 4 types of coins are 5,7,11,13respectively. Each kind of coin has an unlimited supply.

There are q queries. The jjj-th query is described as an integer number xxx. The answer to the query is the minimum number of coins that is necessary to obtain the value xxx using some subset of coins (Alice or Bob). If it is impossible to obtain the value, the answer to the jjj-th query is −1. If both of them can obtain the minimum number, output "both". In the other case, you should output either "A" if Alice can obtain the minimum number or "B" if Bob can obtain the minimum number. 

输入描述:

The first line of the input contains an integer qqq (1≤q≤1051\le q\le 10^51≤q≤105) --- the number of queries.

Each of the following nnn lines contains an integer xxx (0≤x≤1090\le x \le 10^90≤x≤109), the value obtained.

输出描述:

For each query, print a single line according to the description above.

示例1

输入

复制4 0 1 2 3

4
0
1
2
3

输出

复制both -1 A A

both
-1
A
A

这一题是一个需要压缩数组大小的dp问题,一开始我们一看数据量是1e9,立刻就否认了使用dp的可能性,但是随着我队友的发现,他说可以利用如果数据足够大,就肯定是有最大的质数作为一个组成部分,我们仔细讨论,发现数值可以压缩到200以下,因为当数据大于200的时候,Alice必然是可以使用19作为一个加法成员的。

举一个例子,Alice想要组成一个x的数,他使用的硬币2元就一定是1个或者2个,如果大于三个,就可以使用2个3元代替,所以硬币2元的数量必然是小于等于2的,同理,他使用的3元的硬币的数量必然是小于等于16,如果大于16,就可以使用3个17来代替,所以他的目标数据大小可以压缩到5000之内,这样就变成了一个传统的找可以组成x元的最小方案数的dp问题。

转移方程是a[i] = min(a[i] , a[i - c[j]] + 1);

                  b[i] = min(b[i] ,  b[i - d[j]] + 1);

代码:

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#include<deque>
typedef long long ll;
typedef pair<ll, ll>PII;
const int N =5050;
ll a[N],b[N];
ll c[4] = {2 ,3 , 17,19};
ll d[4] = { 5,7,11,13 };
void work()
{
    memset(a, 0x3f, sizeof(a));
    memset(b, 0x3f, sizeof(b));
    ll n;
    cin >> n;
    if (n == 0)
    {
        cout << "both\n";
        return;
    }
    else if (n == 1)
    {
        cout << -1 << '\n';
        return;
    }
    /*else if (n == 2 || n == 3 || n == 4 || n == 6 || n == 8  || n == 9 || n == 10 || n == 14 || n == 19)
    {
        cout << "A\n";
        return;
    }*/
    ll num1 = 0, num2 = 0;
    ll minn1 = 1e9;
    ll minn2 = 1e9;
    ll p = 0;

    ll an = n,bn = n;
    if (n >= 5000)
    {
        ll x = 5000 / 19;
        p = n / 19;
        p -= x;
        num1 += p + 1;
        an = n - (p + 1) * 19;

        ll y = 5000 / 13;
        p = n / 13;
        p -= y;
        num2 += p + 1;
        bn = n - (p + 1 ) * 13;
    }
    a[0] = 0, b[0] = 0;
    for (int i = 0; i < 4; i++)
    {
        for (int j = c[i]; j < 5000; j++)
        {
            a[j] = min(a[j], a[j - c[i]] + 1);
        }
    }
    for (int i = 0; i < 4; i++)
    {
        for (int j = d[i]; j < 5000; j++)
        {
            b[j] = min(b[j], b[j - d[i]] + 1);
        }
    }
    if (a[an] + num1 < b[bn] + num2)
    {
        cout << "A\n";
        return;
    }
    else if (a[an] + num1 == b[bn] + num2)
    {
        cout << "both\n";
        return;
    }
    else
    {
        cout << "B\n";
        return;
    }
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    ll t = 1;
    cin >> t;
    while (t--)
    {
        work();
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值