题解系列015 + 比赛系列004 | CSDN 第十三届编程竞赛题解 + 建议

建议与反馈

这次比赛恰好有部分时间冲突,因此第三题看了发一会现没怎么理解就胡乱做了一通过了(当然鉴于不少 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=2n1nZ+}.

当然答案本身不重要,但探索过程给了我们一个重要信息:从小到大局部扩大选取的面值范围

在这里插入图片描述

因而模拟如下即可:

代码
#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),x0x<k,xkx1

因此问题有通式如下:

方法数 = ( 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(n1)m)+2(k(m1)n))+两个条件不满足 (4(k(n1)(m1))+(k(n2)m)+(k(m2)n))三个条件不满足 (2(k(n2)(m1))+2(k(m2)(n1)))+四个条件不满足 (k(n2)(m2))

由于害怕数据范围爆掉,所以用了 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),x0x<k,xkx1)。

代码
# 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)

欢迎关注我的博客!
我的 GitHub 账号: 欢迎 Fork + PR!
我的洛谷账号:这是我
我的洛谷团队:这是我的团队
欢迎大家关注我,在项目上与我协作哦!
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值