Skip to content

喵~ Codeforces 486A - Calculating Function 解题报告喵~

哈喵~!各位主人,今天我们来看一道非常有趣的数学题,来自 Codeforces 的 486A - Calculating Function。这道题看起来有点吓人,因为数字 n 可以非常非常大,但是只要我们静下心来,像小猫咪一样仔细观察,就能发现其中的小秘密哦~ ฅ'ω'ฅ


题目大意喵

题目让我们计算一个函数 f(n) 的值,这个函数是这样定义的:

f(n) = -1 + 2 - 3 + 4 - 5 + ... + (-1)^n * n

简单来说,就是一个从 1 到 n 的交错序列求和。奇数项是负的,偶数项是正的。

输入:一个正整数 n (1 ≤ n ≤ 10^15)。 输出f(n) 的计算结果。

注意到 n 的范围了吗?高达 10^15!如果我们用一个循环从 1 加到 n,那肯定会超时(TLE)的啦。所以,我们必须找到一个更聪明的办法,一个 O(1) 的数学方法,喵!


解题思路喵~

让我们来找找规律吧!就像猫咪寻找藏起来的毛线球一样,耐心一点总能发现线索的~

我们可以把这个序列两两分组,看看会发生什么奇妙的事情:

(-1 + 2) + (-3 + 4) + (-5 + 6) + ...

看到了吗?每一对相邻的数(一个负奇数和一个正偶数)加起来都等于 +1 耶!

-1 + 2 = 1-3 + 4 = 1-5 + 6 = 1

这个发现是解决问题的关键哦!现在我们只需要根据 n 的奇偶性来分情况讨论啦。

情况一:当 n 是偶数时

如果 n 是一个偶数,比如 n = 4 或者 n = 10,那么整个序列正好可以被分成 n / 2 个这样的小组。

f(4) = (-1 + 2) + (-3 + 4) = 1 + 1 = 2 这里有 4 / 2 = 2 组。

f(10) = (-1+2) + (-3+4) + (-5+6) + (-7+8) + (-9+10) = 1 + 1 + 1 + 1 + 1 = 5 这里有 10 / 2 = 5 组。

每一组的和都是 1,总共有 n / 2 组。所以,当 n 是偶数时,f(n) 的结果就是 n / 2!是不是超级简单喵?

情况二:当 n 是奇数时

如果 n 是一个奇数,比如 n = 5,那么序列的前 n - 1 项可以完美地配成对,但最后一项 -n 会被孤零零地剩下来。

f(5) = (-1 + 2) + (-3 + 4) - 5

前面 n - 1 (也就是 4) 项可以分成 (n - 1) / 2 组,每组的和是 1。所以这部分的和是 (n - 1) / 2

然后,我们还要加上那个被剩下的孤单的最后一项 -n

所以,f(n) = (n - 1) / 2 - n

我们来化简一下这个式子: f(n) = (n - 1 - 2n) / 2 = (-n - 1) / 2 = -(n + 1) / 2

我们用 n = 5 来验证一下: f(5) = -(5 + 1) / 2 = -6 / 2 = -3。 而 (-1+2)+(-3+4)-5 = 1+1-5 = -3。完全正确,太棒了喵!

总结一下我们的发现:

  • 如果 n 是偶数,f(n) = n / 2
  • 如果 n 是奇数,f(n) = -(n + 1) / 2

解题代码(C++)

有了上面的数学公式,代码就变得非常简单啦。只需要判断一下 n 的奇偶性,然后套用对应的公式就好啦。

cpp
#include <iostream>

int main() {
    // 这两行是为了让输入输出更快一点,是个好习惯喵~
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    // 因为 n 最大有 10^15,所以要用 long long 类型才装得下哦!
    long long n;
    std::cin >> n;

    // 判断 n 是不是偶数
    if (n % 2 == 0) {
        // 如果是偶数,就输出 n / 2
        std::cout << n / 2 << std::endl;
    } else {
        // 如果是奇数,就输出 -(n + 1) / 2
        std::cout << -(n + 1) / 2 << std::endl;
    }

    return 0;
}

知识点小课堂喵

  1. 数学规律观察 (Mathematical Pattern Recognition) 这道题的核心就是通过观察、分组,找到序列求和的规律。在算法竞赛中,很多看似复杂的题目背后都隐藏着简单的数学模式,善于发现规律是成为高手的必备技能之一哦!

  2. 数据类型与溢出 (Data Types and Overflow) 题目的输入 n 高达 10^15。在 C++ 中,一个标准的 int 类型通常只能表示到 2 * 10^9 左右,完全不够用。如果我们用了 int,就会发生“整数溢出”,导致计算结果错误。因此,必须使用能表示更大范围整数的 long long 类型。这是写代码时要特别小心的地方,喵~

  3. 时间复杂度 (Time Complexity) 暴力循环求解的时间复杂度是 O(n)。当 n10^15 时,计算机会算到天荒地老。而我们的数学方法只需要进行几次判断和除法运算,与 n 的大小无关,时间复杂度是 O(1),也就是常数时间。这使得我们能瞬间算出结果,轻松通过题目!

好啦,今天的解题报告就到这里啦!是不是很简单很有趣呢?只要我们像猫咪一样保持好奇心和耐心,再难的题目也能找到突破口。主人下次也要加油哦,喵~!(>^ω^<)

Released under the MIT License.