历年的NOIP回顾

2013年

普及

1.麦森数

  • 如何求一个数字的位数?

我们发现在 1 0 k ∼ 1 0 k + 1 − 1 , ( k ≥ 0 ) 10^k \sim 10^{k + 1}-1, (k \ge 0) 10k10k+11,(k0) 之间的数均有 k + 1 k + 1 k+1 位。因此对于任意正整数 x x x,它的位数是 ⌊ log ⁡ 10 x ⌋ + 1 \lfloor \log_{10}x \rfloor + 1 log10x+1
而由于2的整次幂的末位数字不为0,因此 2 P − 1 2^P - 1 2P1 的位数和 2 P 2^P 2P 的位数相同,所以 2 P − 1 2^P - 1 2P1 的位数是 ⌊ log ⁡ 10 2 P ⌋ + 1 = ⌊ P log ⁡ 10 2 ⌋ + 1 \lfloor \log_{10}{2^P} \rfloor + 1 = \lfloor P\log_{10}2 \rfloor + 1 log102P+1=Plog102+1
cmath库中有函数 log10(),直接使用即可。原地址

  • 高精度的乘法可以变成是矩阵乘法。

那么在矩阵乘法中,若数组是从0开始作为下标的话: c [ ( i + j ) ] = a [ i ] ∗ b [ j ] c[(i+j)]=a[i]*b[j] c[(i+j)]=a[i]b[j],注意统计进位。

这里是代码的实现部分

2.

  • C a t a l a n Catalan Catalan h ( n ) h(n) h(n) 的若干种求法:

h ( n ) = 1 , 1 , 2 , 5 , 14 , 42 , 132 , 429 , 1430 , 4862 , 16796 , 58786 , 208012 , 742900 , . . . h(n)=1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, ... h(n)=1,1,2,5,14,42,132,429,1430,4862,16796,58786,208012,742900,...

  1. h ( n ) = C 2 ∗ n n − C 2 ∗ n n − 1 h(n)=C_{2*n}^{n}-C_{2*n}^{n-1} h(n)=C2nnC2nn1
  2. h ( n ) = C 2 ∗ n n n + 1 h(n)=\frac{C_{2*n}^{n}}{n+1} h(n)=n+1C2nn
  3. h ( n ) = h ( 0 ) ∗ h ( n ) + h ( 1 ) ∗ h ( n − 1 ) + … … + h ( n − 1 ) ∗ h ( 1 ) + h ( n ) ∗ h ( 0 ) h(n)=h(0)*h(n)+h(1)*h(n-1)+……+h(n-1)*h(1)+h(n)*h(0) h(n)=h(0)h(n)+h(1)h(n1)++h(n1)h(1)+h(n)h(0)
  4. h ( n ) = ( 4 ∗ n − 2 ) ∗ h ( n − 1 ) n + 1 h(n)=\frac{(4*n-2)*h(n-1)}{n+1} h(n)=n+1(4n2)h(n1)
  • 组合数的范围大概是在 C 67 67 C_{67}^{67} C6767之内的时候是在 l o n g l o n g longlong longlong的承受范围之内的。

这是代码的实现部分

3.乒乓球

  • 注意专业知识的储备:

在11分制下,一局比赛结束的条件是:某一方达到11分,且分差达到2;
在21分制下,一局比赛结束的条件是:某一方达到21分,且分差达到2;

这是代码的实现部分

提高

1.侦探推理

  • 鬼畜模拟题。

我们需要思考的是:
我们需要用什么作为我们判断一个人是否说谎的标准?

我们显然是可以用阶乘的暴力枚举每一个人时候说谎,或者是用阶乘的暴力枚举究竟谁是罪犯?但是,我们真的需要这样吗?

我们可以发现的是在证词中还有另外的一个不相关的信息:星期几?换一个思路:如果我们是枚举的周几的话,是不是就可以直接判断一部分人是否说谎,这样子操作复杂度还低。

2.加分二叉树

  • 区间DP+前序求解。

问题:如何看出这是一个区间DP的??


2014年

普及

1.FBI树

  • 二叉树的前中后遍历顺序的实现

我们可以采用递归实现这个问题
例子:前序遍历
该节点的实现操作(根)
dfs(l, mid)(左节点)
dfs(mid+1,r) (右节点)

这里是代码实现部分

2.火星人

  • S T L STL STL大法好啊

组合数学中经常用到排列,这里介绍一个计算序列全排列的函数:next_permutation(start,end),和prev_permutation(start,end)。这两个函数作用是一样的,区别就在于前者求的是当前排列的下一个排列,后一个求的是当前排列的上一个排列。至于这里的“前一个”和“后一个”,我们可以把它理解为序列的字典序的前后,严格来讲,就是对于当前序列pn,他的下一个序列pn+1满足:不存在另外的序列pm,使pn<pm<pn+1.(转自于next_permutation 函数的使用 poj1256)

  • S T L STL STL的好处:代码实现方便,这里的函数是专门针对于字典序进行操作的,所以有一些根据字典序进行操作的排列,我们就可以直接使用 S T L STL STL

这里是代码的实现部分


2018年

提高

1.铺设道路

  • 中位数的妙用

我们考虑一下把原序列变成是差分序列,那么这样的话,我们就会得到一个类似于这样的差分序列:-1 5 2 -3 4 正负交替的数字。我们知道的是如果是在[l, r]进行修改的话,我们只需要在 l 的位置,在 r+1 的位置上进行操作

因为 b a l a n c e d balanced balanced n u m b e r number number 的定义是:区间内的每一个数上的数字都要出现在区间和中。那么,当有两个数字上的位置数字冲突时就会在和 s u m sum sum 中组成一个新的数字,那么这个位置上的数字就不会再出现在和 s u m sum sum 上,所以此时的两个数字就可以组成 u n b a l a n c e d   n u m b e r unbalanced \ number unbalanced number

因为,我们要找到最小的一段不合法的数字的和,如果我们可以找到一段数字的话:也就说明了这一段数字中有至少两个数字在同一位上有同时出现的数字造就了他们的不合法。那么,我们贪心的选取的话,就是选取最少的数字组成最小的和,也就是可以只选取两个数字。

所以,我们的问题就转化成了:如何找到两个数字使得他们的和最小,这两个数字可选当且仅当他们最少有同一位置上数字同时出现。

因为这个问题是和数位有关系的,而且值域最大是 2 e 9 2e9 2e9,所以,我们可以单独的把每一个位置的数字拿出来处理。

因为题目中的操作是单点修改区间查询,所以,我们要考虑可以实现这些操作的数据结构:这个时候就可以发挥线段树的作用了。

我们可以建10棵线段树动态维护每一个数字的删除,添加以及查询。

但是,有一个问题是:当我们知道了某两个数字在同一位置上有冲突的时候,如何确定这两个数字是我们要找的两个数字呢?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值