- 邓文瞻 的博客
[GESP202506 二级] 数三角形
- @ 2026-9-17 11:05:19
如果 ,阁下该如何应对?
算法:
#include <cstdio>
int main() {
int n, s; // 大数据要用long long
scanf("%d", &n);
for (int a = 1; a <= n; a++) s += (n - a + 1) >> (a & 1);
printf("%d", s);
return 0;
}
这是怎么来的?
题目要求计算有多少对正整数 满足 且 为整数。
转化条件:当 为奇数时, 为不超过 的偶数;当 为偶数时, 为不超过 的正整数;(不重复计数)。故答案为 ,其中
$$\begin{align*} f(a)&=\begin{cases}\left\lfloor\dfrac{n-a+1}2\right\rfloor,&a为奇数,\\[10pt]n-a+1,&a为偶数\end{cases}\\ &=\left\lfloor\dfrac{n-a+1}{2^{a\bmod2}}\right\rfloor. \end{align*}$$这就是程序里的 (n - a + 1) >> (a & 1)。
算法:
#include <cstdio>
int main() {
int n; // 大数据要用long long
scanf("%d", &n);
printf("%d", n & 1 ? (n * n - 1) * 3 >> 3 : n * (n * 3 + 2) >> 3);
return 0;
}
这是怎么来的?
我们引入序号 :
- 当 为奇数时,将其表示为 ,其中 ;
- 当 为偶数时,将其表示为 ,其中 。
情况一:当 为奇数时
设 (此时 是整数),则奇数 最大为 ,对应 ;偶数 最大为 ,对应 。
- 计算奇数项
代入 ,得 。因为 和 是奇数,所以 是奇数,故 。
对 从 到 求和,得 $\displaystyle S_{\rm odd}=\sum_{k=1}^{m+1}(m-k+1)=\sum_{k=1}^m(m-k+1)$。
令 ,当 从 到 时, 从 到 ,$\displaystyle S_{\rm odd}=\sum_{j=1}^mj=\frac{m(m+1)}2.$
- 计算偶数项
代入 ,得 。
对 从 到 求和,得 $\displaystyle S_{\rm even}=\sum_{k=1}^m2(m-k+1)=2\sum_{j=1}^mj=2\cdot\frac{m(m+1)}2=m(m+1).$
- 合并得到
$S=S_{\rm odd}+S_{\rm even}=\dfrac{m(m+1)}2+m(m+1)=\dfrac{3m(m+1)}2$,将 代回得 $S=\dfrac{3\cdot\frac{n-1}2\cdot\frac{n+1}2}2=\dfrac{3(n-1)(n+1)}8=\dfrac{3(n^2-1)}8.$
情况二:当 为偶数时
设 (此时 是整数),则奇数 最大为 ,对应 ;偶数 最大为 ,对应 。
- 计算奇数项
代入 ,得 。这是一个偶数,故 。
对 从 到 求和,得 $\displaystyle S_{\rm odd}=\sum_{k=1}^m(m-k+1)=\sum_{j=1}^mj=\frac{m(m+1)}2.$
- 计算偶数项
代入 ,得 。
对 从 到 求和,得 $\displaystyle S_{\rm even}=\sum_{k=1}^m(2m-2k+1)=\sum_{k=1}^m[2(m-k)+1]$。
令 ,当 从 到 时, 从 到 ,$\displaystyle S_{\rm even}=\sum_{j=0}^{m-1}(2j+1)=2\cdot\frac{(m-1)m}2+m=m^2-m+m=m^2.$
- 合并得到
$S=S_{\rm odd}+S_{\rm even}=\dfrac{m(m+1)}2+m^2=\dfrac{3m^2+m}2$,将 代回得 $S=\dfrac{3(\frac n2)^2+\frac n2}2=\dfrac{\frac{3n^2}4+\frac n2}2=\dfrac{3n^2+2n}8=\dfrac{n(3n+2)}8.$
最终结果
综上,得
$$S=\begin{cases}\dfrac{3(n^2-1)}{8},&n为奇数,\\[10pt]\dfrac{n(3n+2)}8,&n为偶数.\end{cases}$$这就是程序里的 n & 1 ? (n * n - 1) * 3 >> 3 : n * (n * 3 + 2) >> 3。