建议与反馈
这次比赛恰好有部分时间冲突,因此第三题看了发一会现没怎么理解就胡乱做了一通过了(当然鉴于不少 AK 者的出现,很大程度上是由于我个人理解问题),但同时希望 CSDN 官方能够明确并单独地列出每个输入变量的含义与范围(同时建议 Markdown + LaTeX 排版),从而帮助参赛者更块地理解题意。
一、总体情况
得分:25+25+5+25=80(排名第7)
二、题目分析
第一题
题目
分析
虽然笔者不搞 OI, 但是想必这道题对于接触过 c++ 竞赛基础的人来说一定是耳熟能详。(原题传送门)当然这题本身难度也很小,只要用 for
循环判断即可:
代码
#include <iostream>
using namespace std;
int main()
{
int a[15];
int h, tt, cnt=0;
for (int i = 1; i <= 10; i++)
cin >> a[i];
cin >> h;
tt = h + 30;
for (int i = 1; i <= 10; i++)
{
if (a[i] <= tt)
{
cnt++;
}
}
cout << cnt;
return 0;
第二题
题目
分析
这里给出一个不是最有,但最为直接的方法。
首先可以思考的是,“最少”用哪些面值各一次可以表出所有正整数?
1 显然必须在内,但有了 1 不够,2 无法表示,因此 2 也必须在内。有了 [1, 2]
之后只能表示 [1, 2, 3]
,因此还需要 4…… 经过归纳可以得到所求为
{
a
n
=
2
n
−
1
∣
n
∈
Z
+
}
\{a_n=2^{n-1}\mid n\in\mathbb{Z}^{+}\}
{an=2n−1∣n∈Z+}.
当然答案本身不重要,但探索过程给了我们一个重要信息:从小到大局部扩大选取的面值范围。
因而模拟如下即可:
代码
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n, m;
int a[1001];
int sum, ans = 0;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
a[n + 1] = m;
sort(a + 1, a + 1 + n + 1);
if (a[1] != 1)
{
printf("No answer!!!\n");
return 0;
}
// 从小面值组合往大面值试
for (int i = 1; i <= n; i++)
{
while (sum < a[i + 1] - 1)
{
sum += a[i];
// cout << i << " " << sum << endl;
// cout << ans << endl;
ans++;
if (sum >= m)
{
cout << ans;
return 0;
}
}
}
cout << ans + 1;
return 0;
}
第三题
题目
可能是我理解能力比较差,但没看懂题目两个样例在干什么……大概按照“进制”的意思写了一个特判 0 和十进制的(虽然还是没理解)算是捡了点小分。
第四题
题目
分析
读完题目,顿感这是一道组合问题……题目是要求四个条件(即四个边有豚鼠)都被满足,但注意到同一边界的豚鼠被排列的前后顺序不影响,因此正面做不太行。再看问题的反面:每次只要限制住多个不满足即可,而这是十分容易的(很容易想到,相当于是划定了一块子区域随便排),而如果重复呢?交给容斥原理即可(或者用 Venn 图理解)。
我们注意到, x x x 个格子随便排 k k k 个豚鼠(每个豚鼠在不同的格子)的方法数是 { 0 , x ≤ 0 或 x < k ( x k ) , x ≥ k 且 x ≥ 1 \begin{cases} 0 &, x\leq 0 \text{或} x<k \\ \binom{x}{k} &, x\geq k \text{且} x\geq 1 \end{cases} {0(kx),x≤0或x<k,x≥k且x≥1
因此问题有通式如下:
方法数 = ( n m k ) − ( 2 ( ( n − 1 ) m k ) + 2 ( ( m − 1 ) n k ) ) ⏟ 一个条件不满足 + ( 4 ( ( n − 1 ) ( m − 1 ) k ) + ( ( n − 2 ) m k ) + ( ( m − 2 ) n k ) ) ⏟ 两个条件不满足 − ( 2 ( ( n − 2 ) ( m − 1 ) k ) + 2 ( ( m − 2 ) ( n − 1 ) k ) ) ⏟ 三个条件不满足 + ( ( n − 2 ) ( m − 2 ) k ) ⏟ 四个条件不满足 \begin{aligned} \text{方法数}&=\binom{nm}{k}-\underset{\text{一个条件不满足}}{\underbrace{\left( 2\binom{\left( n-1 \right) m}{k}+2\binom{\left( m-1 \right) n}{k} \right) }}\\ &+\underset{\text{两个条件不满足}}{\underbrace{\left( 4\binom{\left( n-1 \right) \left( m-1 \right)}{k}+\binom{\left( n-2 \right) m}{k}+\binom{\left( m-2 \right) n}{k} \right) }}\\ &-\underset{\text{三个条件不满足}}{\begin{array}{c} \underbrace{\left( 2\binom{\left( n-2 \right) \left( m-1 \right)}{k}+2\binom{\left( m-2 \right) \left( n-1 \right)}{k} \right) }\\ \end{array}}\\ &+\underset{\text{四个条件不满足}}{\underbrace{\binom{\left( n-2 \right) \left( m-2 \right)}{k}}}\\ \end{aligned} 方法数=(knm)−一个条件不满足 (2(k(n−1)m)+2(k(m−1)n))+两个条件不满足 (4(k(n−1)(m−1))+(k(n−2)m)+(k(m−2)n))−三个条件不满足 (2(k(n−2)(m−1))+2(k(m−2)(n−1)))+四个条件不满足 (k(n−2)(m−2))
由于害怕数据范围爆掉,所以用了 python
。唯一需要注意的是在定义组合数函数的时候别忘了把
0
0
0 的情况加进去(就是上面这个
{
0
,
x
≤
0
或
x
<
k
(
x
k
)
,
x
≥
k
且
x
≥
1
\begin{cases} 0 &, x\leq 0 \text{或} x<k \\ \binom{x}{k} &, x\geq k \text{且} x\geq 1 \end{cases}
{0(kx),x≤0或x<k,x≥k且x≥1)。
代码
# 4
from math import factorial
def comb(n,m):
if n<0 or m>n:
return 0
else:
return factorial(n)/(factorial(n-m) * factorial(m))
class Solution:
def __init__(self) -> None:
pass
def solution(self, n):
result = None
r = n[0]
c = n[1]
k = n[2]
result = comb(r*c, k)-2*comb((r-1)*c, k)-2*comb((c-1)*r, k)
result = result +comb((r-2)*c, k)+comb(r*(c-2), k)+4*comb((r-1)*(c-1), k)
result = result - 2*comb((r-2)*(c-1), k)-2*comb((c-2)*(r-1), k)
result = result+comb((r-2)*(c-2), k)
return '{:.0f}'.format(result)
if __name__ == "__main__":
n = [int(item) for item in input().strip().split()]
sol = Solution()
result = sol.solution(n)
print(result)