CSDN编程竞赛第13期题解

CSDN编程竞赛报名地址:https://edu.csdn.net/contest/detail/27
(请不要删掉此地址) 

 

1. 题目名称:陶陶摘苹果

陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 10 个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个 30 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。 现在已知 10 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹果的数目。假设她碰到苹果,苹果就会掉下来。 

        根据题意可知道陶陶能摘到苹果的最大高度应该加上凳子的30cm。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int a[maxn];
int main()
{
    for (int i = 0; i < 10; ++i)
        scanf("%d", a + i);
    int h, ans = 0;
    scanf("%d", &h);
    for (int i = 0; i < 10; ++i)
        if (a[i] <= h + 30)
            ++ans;
    printf("%d\n", ans);
    return 0;
}

2. 题目名称:硬币的面值

小A有n枚硬币,现在要买一样不超过m元的商品,他不想被找零,同时又不想带太多的硬币,且硬币可以重复,现在已知 这n枚硬币的面值,请问最少需要多少枚硬币就能组合成所有可能(即能组合成1-m任意之间的数字)的价格?

         根据题意,首先要有1元硬币,否则无解。然后找最小的a[i] > sum + 1。

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    vector<int> a(n, 0);
    for (int i = 0; i < n; ++i)
        scanf("%d", &a[i]);
    sort(a.begin(), a.end());
    if (a[0] != 1)
        puts("No answer!!!");
    else
    {
        int ans = 0, sum = 0;
        while (sum < m)
        {
            int x = upper_bound(a.begin(), a.end(), sum + 1) - a.begin();
            --x;
            ++ans;
            sum += a[x];
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

3. 题目名称:公司新表

公司里为了凸显公司的特性。安装了一个n进制表。 已知新的表的时间是”H:M”。 时间合法的定义为H<=23 && M<=59。 时间有多少种进制定义的方式,依次打印出来。 如果有无数种解输出”-1”,不存在输出”0”。

        这题我只拿了80分,下面是我的一些想法,仅供参考。

        根据题意,应该是不超过60进制。然后H和M都为0时有无数种解,其他枚举所有进制,判断H和M是否不超过限制以及进制数字。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
char a[maxn], b[maxn], s[maxn];
void solve()
{
    int n = strlen(a), m = strlen(b), zeroa = 1, zerob = 1;
    for (int i = 0; i < n; ++i)
        if (a[i] != '0')
        {
            zeroa = 0;
            break;
        }
    for (int i = 0; i < m; ++i)
        if (b[i] != '0')
        {
            zerob = 0;
            break;
        }
    if (zeroa + zerob == 2)
    {
        puts("-1");
        return;
    }
    vector<int> ans;
    for (int i = 2; i < 60; ++i)
    {
        int h = 0;
        for (int j = 0; j < n; ++j)
        {
            int c;
            if (isdigit(a[j]))
                h = h * i + (c = a[j] - '0');
            else if (a[j] < 'A' || a[j] > 'Z')
                h = 25;
            else
                h = h * i + (c = a[j] - 'A' + 10);
            if (c >= i)
                h = 25;
            if (h >= 24)
                break;
        }
        int m2 = 0;
        for (int j = 0; j < m; ++j)
        {
            int c;
            if (isdigit(b[j]))
                m2 = m2 * i + (c = b[j] - '0');
            else if (b[j] < 'A' || b[j] > 'Z')
                m2 = 60;
            else
                m2 = m2 * i + (c = b[j] - 'A' + 10);
            if (c >= i)
                m2 = 60;
            if (m2 >= 60)
                break;
        }
        if (h >= 24 || m2 >= 60)
            continue;
        ans.emplace_back(i);
    }
    if (ans.empty())
    {
        puts("0");
        return;
    }
    for (int i = 0, sz = ans.size(); i < sz; ++i)
        printf("%d%c", ans[i], " \n"[i == sz - 1]);
    return;
}
int main()
{
    scanf("%s", s);
    int p = 0, slen = strlen(s);
    for (int i = 0; i < slen; ++i)
        if (s[i] == ':')
        {
            p = i;
            break;
        }
    memcpy(a, s, p);
    a[p] = '\0';
    memcpy(b, s + p + 1, slen - p - 1);
    b[slen - p - 1] = '\0';
    solve();
    return 0;
}

 

4. 题目名称:小豚鼠排排坐

小艺酱买了一个由一排排格子组成的小房子n*m,她想让k个小豚鼠每个小豚鼠都有自己的格子。 但是为了不浪费空间,她想要最边角的一圈2*(n+m-2)每行每列的格子都有一个小豚鼠居住。 具体来说,假设这k只小豚鼠的格子坐标为(x1, y1), (x2, y2),…,(xk, yk),则需要满足存在 1 < a,b,c,d <= k,使得xa = 1, xb = n, yc = 1, yd = m (a,b,c,d可以重复).

        由于数据范围小,可以直接二进制枚举所有情况,然后用位运算check。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 55;
int main()
{
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    int N = n * m, ans = 0;
    int mask1 = (1 << m) - 1, mask2 = mask1 << ((n - 1) * m), mask3 = 0, mask4 = 0;
    for (int i = 0; i < N; i += m)
        mask3 |= 1 << i;
    for (int i = m - 1; i < N; i += m)
        mask4 |= 1 << i;
    for (int i = 0; i < 1 << N; ++i)
    {
        if (__builtin_popcount(i) != k)
            continue;
        if ((i & mask1) && (i & mask2) && (i & mask3) && (i & mask4))
            ++ans;
    }
    printf("%d\n", ans);
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值