2014 年普及组初赛整理

这篇博客介绍了如何解决将一定数量的球放入相同袋子的问题,通过列举不同放置方式来求解。文章通过具体例子展示了如何按照有球袋子数进行分类列举,并给出了C++代码实现。同时,还涉及到递归函数的应用和最大子矩阵和的计算方法,包括相关代码示例。

把 MM 个同样的球放到 NN 个同样的袋子里,允许有的袋子空着不放,问共有多少种不同的放置方法?(用 KK 表示)。

例如, M=7M=7,N=3N=3 时,K=8K=8;在这里认为 (5,1,1)(5,1,1) 和 (1,5,1)(1,5,1) 是同一种放置方法。

问:M=8M=8,N=5N=5 时,K=K=__18__

使用列举法解决,注意做到不重、不漏。建议按照有球袋子数分类列举,每种方案严格按照非降排列(省略空袋子):

11 个有球的袋子:(8)(8)

22 个有球的袋子:(1, 7)(2, 6)(3, 5)(4, 4)(1,7)(2,6)(3,5)(4,4)

33 个有球的袋子:(1, 1, 6)(1, 2, 5)(1, 3, 4)(2, 2, 4)(2, 3, 3)(1,1,6)(1,2,5)(1,3,4)(2,2,4)(2,3,3)

44 个有球的袋子:(1, 1, 1, 5)(1, 1, 2, 4)(1, 1, 3, 3)(1, 2, 2, 3)(2, 2, 2, 2)(1,1,1,5)(1,1,2,4)(1,1,3,3)(1,2,2,3)(2,2,2,2)

55 个有球的袋子:(1, 1, 1, 1, 4)(1, 1, 1, 2, 3)(1, 1, 2, 2, 2)(1,1,1,1,4)(1,1,1,2,3)(1,1,2,2,2)

故总方案数为 1 + 4 + 5 + 5 + 3 = 181+4+5+5+3=18。

#include <iostream>
using namespace std;
int main()
{
    int a, b, c, d, ans;
    cin >> a >> b >> c;
    d = a - b;
    a = d + c;
    ans = a * b;
    cout << "Ans = " << ans << endl;
    return 0;
}

输入:2 3 4

输出:Ans = 9

按照顺序计算即可,注意不要漏掉提示信息“Ans = ”。

d=a-b=2-3=-1d=a−b=2−3=−1

a=d+c=(-1)+4=3a=d+c=(−1)+4=3

ans=a\times b=3\times =9ans=a×b=3×=9

因此正确答案为“Ans = 9”(不含引号,注意不要漏掉提示信息,也不要漏掉空格)。

#include <iostream>
using namespace std;
int fun(int n)
{
    if(n == 1)
        return 1;
    if(n == 2)
        return 2;
    return fun(n - 2) - fun(n - 1);
}
int main()
{
    int n;
    cin >> n;
    cout << fun(n) << endl;
    return 0;
}

输入:7

输出:-11

fun为递归函数,直接模拟难度较大。如果把fun视为数列,参数 nn 视为该序列的项数,则容易发现,该序列满足 fun(1) = 1, fun(2) = 2, n \ge 3fun(1)=1,fun(2)=2,n≥3时,fun(n) = fun(n - 2) - fun(n - 1)fun(n)=fun(n−2)−fun(n−1)。而本题的目标转化为求数列的第 77 项,因此可以使用递推依次计算数列各项:

(数字删除)下面程序的功能是将字符串中的数字字符删除后输出。请填空。

#include <iostream>
using namespace std;
int delnum(char *s)
{
    int i, j;
    j = 0;
    for(i = 0; s[i] != '\0'; i++)
        if(s[i] < '0' ① s[i] > '9')
        {
            s[j] = s[i];
            ②;
        }
    return ③;
}
const int SIZE = 30;
int main()
{
    char s[SIZE];
    int len, i;
    cin.getline(s, sizeof(s));
    len = delnum(s);
    for(i = 0; i < len; i++)
        cout << ④;
    cout << endl;
    return 0;
}

填空位置 ①:

||

填空位置 ②:

j++

填空位置 ③:

j

填空位置 ④:

s[i]

此题考查简单的字符串处理。delnum就是删数字函数,len是删完的长度,逐个访问字符 s[i],如果不是数字字符,就是有效字符,保存至s[j]j是用来记非数字的最后一位。

①空中需要判断当前字符是不是数字,字符为不为数字的条件此处应该为或关系。

②空中需要将i位置上的字符赋值给j位置。这之后需要更新非数字的最后一位的位置,因此需要将j加一。

③空中需要范围处理后的字符串的长度,因此我们需要返回j

④空我们需要输出最后的结果因此我们需要输出s[i]

(最大子矩阵和)给出 mm 行 nn 列的整数矩阵,求最大的子矩阵和(子矩阵不能为空)。

输入第一行包含两个整数 mm 和 nn,即矩阵的行数和列数。之后 mm 行,每行 nn 个整数,描述整个矩阵。程序最终输出最大的子矩阵和。

#include <iostream>
using namespace std;
const int SIZE = 100;
int matrix[SIZE + 1][SIZE + 1];
int rowsum[SIZE + 1][SIZE + 1]; //rowsum[i][j]记录第 i 行前 j 个数的和
int m, n, i, j, first, last, area, ans;
int main()
{
    cin >> m >> n;
    for(i = 1; i <= m; i++)
        for(j = 1; j <= n; j++)
            cin >> matrix[i][j];
    ans = matrix ①;
    for(i = 1; i <= m; i++)
        ②
    for(i = 1; i <= m; i++)
        for(j = 1; j <= n; j++)
            rowsum[i][j] = ③;
    for(first = 1; first <= n; first++)
        for(last = first; last <= n; last++)
        {
            ④;
            for(i = 1; i <= m; i++)
            {
                area += ⑤;
                if(area > ans)
                    ans = area;
                if(area < 0)
                    area = 0;
            }
        }
    cout << ans << endl;
    return 0;
}

 

填空位置 ①:

[1][1]

填空位置 ②:

rowsum[i][0]=0;

填空位置 ③:

rowsum[i][j-1]+matrix[i][j]

填空位置 ④:

area=0

填空位置 ⑤:

rowsum[i][last]-rowsum[i][first-1]

本题解决最大子矩阵和所用的算法:计算数组rowsum;枚举子矩阵的左边界first和右边界last,将原问题转化为求解一维的最大子段和问题,用贪心法即可解决。

①因为所求最大子矩阵和所涉及的子矩阵不能为空,必须有一个初值,所以我们需要将ans设置为矩阵的左上角元素,也就是 [1][1][1][1],取其他单元格的值也可以;

②因为后面要求每行前缀和,所以需要将 00 列清零,用于之后的统计;

③求当前行到当前列的前缀和,使用前缀和的方法统计每行的sum值;

④从first列到last列之间求最大子段和,需要将当前的值初始化为 00;

⑤这里求第i行的first列到last列之间的数值和,这里采用前缀和方法来加速计算过程。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值