欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

NOIP2014普及组初赛难点整理

程序员文章站 2022-07-08 19:12:28
问题求解把 MMM 个同样的球放到 NNN 个同样的袋子里,允许有的袋子空着不放,问共有多少种不同的放置方法?(用 KKK 表示)。例如, M=7M=7M=7,N=3N=3N=3 时,K=8K=8K=8;在这里认为 (5,1,1)(5,1,1)(5,1,1) 和 (1,5,1)(1,5,1)(1,5,1) 是同一种放置方法。问:M=8M=8M=8,N=5N=5N=5 时,K=K=K=____。【解析】nnn个相同的球放入mmm个相同的盒子(n≥mn≥mn≥m),可以有空盒时的放法种数等于将nnn分解...

问题求解

  1. MM 个同样的球放到 NN 个同样的袋子里,允许有的袋子空着不放,问共有多少种不同的放置方法?(用 KK 表示)。例如, M=7M=7N=3N=3 时,K=8K=8;在这里认为 (5,1,1)(5,1,1)(1,5,1)(1,5,1) 是同一种放置方法。
    问:M=8M=8N=5N=5 时,K=K=____。
    【解析】nn个相同的球放入个相同的盒子(nmn≥m),可以有空盒时的放法种数等于将nn分解为个、(1)(m-1)个、(2)(m-2)个、…、22个、11个数的和的所有种数之和。
    8分解为11个数:8,共11
    8分解为22个数:1+72+63+54+5,共44
    8分解为33个数:1+1+61+2+51+3+42+2+42+3+3,共55
    8分解为44个数:1+1+1+51+1+2+41+1+3+31+2+2+32+2+2+2,共55
    8分解为55个数:1+1+1+1+41+1+1+2+31+1+2+2+2,共33
    答案:18
  2. 如图所示,图中每条边上的数字表示该边的长度,则从 AAEE 的最短距离是____。
    NOIP2014普及组初赛难点整理
    【解析】正权图的最短路,可以使用Dijkstra算法求解。

阅读程序写结果

#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
【解析】模拟递归调用的结果如下:

f(1) f(2) f(3) f(4) f(5) f(6) f(7)
1 2 -1 3 -4 7 -11

输出:-11
2.

#include <iostream>
using namespace std;
const int SIZE = 100;
int main()
{
    int p[SIZE];
    int n, tot, i, cn;
    tot = 0;
    cin >> n;
    for(i = 1; i <= n; i++)
        p[i] = 1;
    for(i = 2; i <= n; i++)
    {
        if(p[i] == 1)
            tot++;
        cn = i * 2;
        while(cn <= n)
        {
            p[cn] = 0;
            cn += i;
        }
    }
    cout << tot << endl;
    return 0;
}

输入:30
输出:10
【解析】埃氏筛素数法。
对正实数xx,定义π(x)π(x)为不大于xx的素数个数, π(x)x/lnxπ(x)≈x/ln x, 其中lnx=logexlnx=log_e^x,为xx的自然对数, e=2.718281828...e=2.718281828...ln303ln30≈3

完善程序

(最大子矩阵和)给出 mmnn 列的整数矩阵,求最大的子矩阵和(子矩阵不能为空)。
输入第一行包含两个整数 mmnn,即矩阵的行数和列数。之后 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;
}

【解析】利用前缀和的思想,计算出矩阵第i行前j列的和rowsum[i][j]。枚举所有列的组合,求出子矩阵和的最大值。
- 空①,初始化ans,让其等于矩阵第一行第一列的值matrix[1][1],所以应填入[1][1]
- 空②,初始化每行前缀和数组的第0项,将其置为00,用于之后计算前缀和,所以应填入rowsum[i][0]=0
- 空③,计算第i行的前缀和,所以应填入rowsum[i-1]+matrix[i][j]
- 空④,初始化area00,所以应填入area=0
- 空⑤,使用前缀和数组计算first列到last列的和,rowsum[i][last]-rowsum[i][first-1]

本文地址:https://blog.csdn.net/qiaoxinwei/article/details/107889469