题面


如果 n≤109n\le10^9,阁下该如何应对?

O(n)O(n) 算法:

#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;
}

这是怎么来的?

题目要求计算有多少对正整数 (a,b)(a,b) 满足 a,b≤na,b\le n 且 ab2\dfrac{ab}2 为整数。

转化条件:当 aa 为奇数时,bb 为不超过 nn 的偶数;当 aa 为偶数时,bb 为不超过 nn 的正整数;b≥ab\ge a(不重复计数)。故答案为 ∑a=1nf(a)\displaystyle\sum_{a=1}^nf(a),其中

$$\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)。


O(1)O(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;
}

这是怎么来的?

我们引入序号 kk:

  • 当 aa 为奇数时,将其表示为 a=2k−1a=2k-1,其中 k≥1k\ge1;
  • 当 aa 为偶数时,将其表示为 a=2ka=2k,其中 k≥1k\ge1。

情况一:当 nn 为奇数时

设 n=2m+1n=2m+1(此时 m=n−12m=\dfrac{n-1}2 是整数),则奇数 aa 最大为 2m+12m+1,对应 k=m+1k=m+1;偶数 aa 最大为 2m2m,对应 k=mk=m。

  1. 计算奇数项 SoddS_{\rm odd}

代入 a=2k−1a=2k-1,得 n−a+1=(2m+1)−(2k−1)+1=2m−2k+3n-a+1=(2m+1)-(2k-1)+1=2m-2k+3。因为 nn 和 aa 是奇数,所以 n−a+1n-a+1 是奇数,故 f(2k−1)=2m−2k+3−12=m−k+1f(2k-1)=\dfrac{2m-2k+3-1}2=m-k+1。
对 kk 从 11 到 m+1m+1 求和,得 $\displaystyle S_{\rm odd}=\sum_{k=1}^{m+1}(m-k+1)=\sum_{k=1}^m(m-k+1)$。
令 j=m−k+1j=m-k+1,当 kk 从 11 到 mm 时,jj 从 mm 到 11,$\displaystyle S_{\rm odd}=\sum_{j=1}^mj=\frac{m(m+1)}2.$

  1. 计算偶数项 SevenS_{\rm even}

代入 a=2ka=2k,得 f(2k)=n−2k+1=(2m+1)−2k+1=2m−2k+2=2(m−k+1)f(2k)=n-2k+1=(2m+1)-2k+1=2m-2k+2=2(m-k+1)。
对 kk 从 11 到 mm 求和,得 $\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).$

  1. 合并得到 SS

$S=S_{\rm odd}+S_{\rm even}=\dfrac{m(m+1)}2+m(m+1)=\dfrac{3m(m+1)}2$,将 m=n−12m=\dfrac{n-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.$


情况二:当 nn 为偶数时

设 n=2mn=2m(此时 m=n2m=\dfrac n2 是整数),则奇数 aa 最大为 2m−12m-1,对应 k=mk=m;偶数 aa 最大为 2m2m ,对应 k=mk=m。

  1. 计算奇数项 SoddS_{\rm odd}

代入 a=2k−1a=2k-1,得 n−a+1=2m−(2k−1)+1=2m−2k+2=2(m−k+1)n-a+1=2m-(2k-1)+1=2m-2k+2=2(m-k+1)。这是一个偶数,故 f(2k−1)=2(m−k+1)2=m−k+1f(2k-1)=\dfrac{2(m-k+1)}2=m-k+1。

对 kk 从 11 到 mm 求和,得 $\displaystyle S_{\rm odd}=\sum_{k=1}^m(m-k+1)=\sum_{j=1}^mj=\frac{m(m+1)}2.$

  1. 计算偶数项 SevenS_{\rm even}

代入 a=2ka=2k,得 f(2k)=n−2k+1=2m−2k+1f(2k)=n-2k+1=2m-2k+1。
对 kk 从 11 到 mm 求和,得 $\displaystyle S_{\rm even}=\sum_{k=1}^m(2m-2k+1)=\sum_{k=1}^m[2(m-k)+1]$。
令 j=m−kj=m-k,当 kk 从 11 到 mm 时,jj 从 m−1m-1 到 00 ,$\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.$

  1. 合并得到 SS

$S=S_{\rm odd}+S_{\rm even}=\dfrac{m(m+1)}2+m^2=\dfrac{3m^2+m}2$,将 m=n2m=\dfrac n2 代回得 $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。