NOIP2017普及组初赛难点整理

本文整理了NOIP2017普及组初赛中的难点,包括选择题的解析,如日期计算、组合计数、图的边数问题等,并涉及实际问题求解,如坐标移动规律探讨,以及程序阅读理解,涵盖递归计算和序列操作。同时,文章提供了程序完善问题的思路,如绳子切割优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

选择题

  1. 201720172017101010111 日是星期日,199919991999101010111 日是( )。
    A. 星期三
    B. 星期二
    C. 星期日
    D. 星期五

【解析】199919991999201720172017年一共是181818年,18×365 %7=(18%7×365%7)%7=418\times 365 \ \% 7=(18\%7\times365\%7)\%7=418×365 %7=(18%7×365%7)%7=4,中间有555个闰年:2000,2004,2008,2012,20162000,2004,2008,2012,20162000,2004,2008,2012,2016(4+5)%7=2(4+5)\%7=2(4+5)%7=2。也就是说199919991999
101010111 日多加两天是星期日,那么199919991999101010111 日是星期五

  1. 甲、乙、丙三位同学选修课程,从 444 门课程中,甲选修 222 门,乙、丙各选修 333 门,则不同的选修方案共有( )种。

【解析】乘法原理:

  • ①甲的方案数:C42=6C_4^2=6C42=6
  • ②乙的方案数:C43=4C_4^3=4C43=4
  • ③丙的方案数:C43=4C_4^3=4C43=4

乘法原理总的方案数为:6×4×4=966\times4\times4=966×4×4=96

  1. GGG 是有 nnn 个结点、mmm 条边(n≤mn \le mnm)的连接图,必须删去 GGG 的( )条边,才能使得 GGG 变成一棵树。

【解析】nnn个结点的树一定有n−1n - 1n1条边,必须从图中删除m−n+1m - n + 1mn+1条边。

  1. 表达式 a*(b+c)*d 的后缀形式是( )。

【解析】套括号提取运算符。 ((a×(b+c))×d),将运算符提取到所在括号的右边:a b c + × d ×

  1. 若串 S="copyright",其子串的个数是( )。

【解析】

  • 长度为0的子串=1
  • 长度为1的子串=9

一共有=1 + 9 + 8 + … + 1 = 46

  1. 十进制小数 13.37513.37513.375 对应的二进制数是( )。

【解析】整数部分除2取余逆序连接,小数部分乘2取整顺序连接

  1. AAABBB 是两个长为 nnn 的有序数组,现在需要将 AAABBB 合并成一个排好序的数组,任何以元素比较作为基本运算的归并算法在最坏情况下至少要做( )次比较。

【解析】在最坏情况下,BBB中除了最后一个数,每个数都会比较2次,一共 2n - 2次,最后一个数只比较1次,所以结果为2n - 1

  1. 一家四口人,至少两个人生日属于同一月份的概率是( )。(假定每个人生日属于每个月份的概率相同且不同人之间相互独立)。

【解析】补集思想 至少两个人生日属于同一月份的概率 = 1 - 所有人的生日都是不同月份的概率。 所有人的生日都是不同月份的概率 = P124124=5596\frac{P_{12}^4}{12^4}= \frac{55}{96}124P124=9655
答案:1−5596=41961-\frac{55}{96}=\frac{41}{96}19655=9641

问题求解

  1. 一个人站在坐标(0,0)(0,0)(00)处,面朝 xxx 轴正方向。第一轮,他向前走 111 单位距离,然后右转;第二轮,他向前走 222 单位距离,然后右转;第三轮,他向前走 333 单位距离,然后右转……他一直这么走下去。请问第 201720172017 轮后,他的坐标是:(___ , ___)。
    在这里插入图片描述

【解析】模拟找规律。

  • 第①轮:x=1,y=0x=1, y=0x=1,y=0
  • 第②轮:x=1,y=−2x=1, y=-2x=1,y=2
  • 第③轮:x=−2,y=−2x=-2, y=-2x=2,y=2
  • 第④轮:x=−2,>y=2x=-2,> y=2x=2,>y=2
  • 第⑤轮:x=3,y=2x=3, y=2x=3,y=2
  • 第⑥轮:x=3,y=−4x=3, y=-4x=3,y=4
  • 第⑦轮:x=−4,y=−4x=-4, y=-4x=4,y=4
  • 第⑧轮:x=−4,y=4x=-4, y=4x=4,y=4
  • 第⑨轮:x=5,y=4x=5, y=4x=5,y=4

每4轮转一圈,第2017轮刚好是从第二象限水平向右走到第一象限,此时:
x=⌊20172⌋+1x= \lfloor \frac{2017}{2}\rfloor + 1x=22017+1y=⌊20172⌋y= \lfloor \frac{2017}{2}\rfloory=22017

  1. 如下图所示,共有 131313个格子。对任何一个格子进行一次操作,会使得它自己以及与它上下左右相邻的格子中的数字改变(由 111000,或由 $0 变 111)。现在要使得所有的格子中的数字都变为 000,至少需要_____次操作。
    在这里插入图片描述

【解析】按照红绿蓝三个格子的顺序进行操作即可。

阅读程序写结果

#include <stdio.h>
int g(int m, int n, int x) {
    int ans=0;
    int i;
    if(n == 1)
        return 1;
    for(i = x; i <= m / n; i++)
        ans += g(m - i, n - 1, i);
    return ans;
}
int main()
{
    int t, m, n;
    scanf("%d%d", &m, &n);
    printf("%d", g(m, n, 0));
    return  0;
}

输入:7 3

【解析】手动模拟递归调用。

在这里插入图片描述
答案:8
2.

#include <iostream>
#include <string>
using namespace std;
int main()
{
    string ch;
    int a[200];
    int b[200];
    int n, i, t, res;
    cin >> ch;
    n = ch.length();
    for(i = 0; i < 200; i++) b[i] = 0;
    for(i = 1; i <= n ; i++) {
        a[i] = ch[i-1] - '0';
        b[i] = b[i-1] + a[i];
    }
    res = b[n];
    t = 0;
    for(i = n; i > 0; i--) {
        if(a[i] == 0) t++;
        if(b[i-1] + t < res) res = b[i-1] + t;
    }
    cout << res << endl;
    return 0;
}

输入:100110101100110110101111000110011010110011011010111100011001101011001101101011110001

【解析】手动模拟。
a[]记录输入的01序列。b[i]表示序列前i个数中1的个数。
变量t记录从序列从后向前(从ni)中0的个数。
变量res为序列前i-1个数中1的个数和从in中0的个数之和的最小值。
1001101011001101101011110001
答案为:11

#include <iostream>
using namespace std;
int main()
{
    int n, m;
    cin >> n >> m;
    int x = 1;
    int y = 1;
    int dx = 1;
    int dy = 1;
    int cnt = 0;
    while(cnt != 2) {
        cnt = 0;
        x = x + dx;
        y = y + dy;
        if(x == 1 || x == n) {
            ++cnt;
            dx = -dx;
        }
        if(y == 1 || y == m) {
            ++cnt;
            dy = -dy;
        }
    }
    cout << x << " " << y << endl;
    return  0 ;
}

【解析】手动模拟,找规律

输入:4 3

n = 4, m = 3, dx = 1, dy = 1, x = 1, y = 1
x = 2, y = 2
x = 3, y = 3, dy = -1
x = 4, y = 2, dx = -1
x = 3, y = 1, dy = 1
x = 2, y = 2
x = 1, y = 3, dx = 1, dy = -1, cnt = 2

答案:1 3
输入:2017 1014

n = 2017, m = 1014, dx = 1, dy = 1, x = 1, y = 1
x = 2, y = 2

x = 1014, y = 1014, dy = -1
x = 1015, y = 1013

x = 2017, y = 1, dx = -1, dy = 1, cnt = 2
答案:2017 1

完善程序

(切割绳子)有 nn 条绳子,每条绳子的长度已知且均为正整数。绳子可以以任意正整数长度切割,但不可以连接。现在要从这些绳子中切割出m条长度相同的绳段,求绳段的最大长度是多少。
输入:第一行是一个不超过 100100100的正整数 nnn,第二行是 nnn 个不超过 10610^6106 的正整数,表示每条绳子的长度,第三行是一个不超过 10810^8108 的正整数 mmm
输出 :绳段的最大长度,若无法切割,输出 Failed。

#include <iostream>
using namespace std;
int n, m, i, lbound, ubound, mid, count;
int  len[100]; //绳子长度
int main()
{
    cin >> n;
    count = 0;
    for (i = 0; i < n; i++) {
        cin >> len[i];
        ①;
    }
    cin >> m;
    if (②) {
        cout << "Failed" << endl;
        return 0;
    }
    lbound = 1 ;
    ubound = 1000000 ;
    while (③) {
        mid = ④;
        count =0 ;
        for (i = 0; i < n; i++ )
            ⑤;
        if (count < m)
            ubound = mid - 1 ;
        else
            lbound = mid ;
    }
    cout << lbound << endl;
    return 0;
}

【解析】二分搜索求切割出m条长度相同的绳段的最大长度。
空①,累加所有绳子的长度,答案:count+=len[i]
空②,如果绳子的总长度<m,那么不可能分割。答案:count<m
空③,二分搜索条件,lbound<ubound
空④,取中间值,注意,所有count>=m的情况都可行,要左边区间的最大值,适用二分搜索模板2,答案:(lbound+ubound+1)/2
空⑤,累加分割的绳子数量,答案:count+=len[i]/m

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少儿编程乔老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值