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;
}