整数和(推公式)
这道题是一道简单题,但是如果我们正常的去暴力,时间复杂度是$O(n)$的,对于这道题是可以过掉的,但一旦扩大数据范围,我们就无法通过暴力去得到正确的答案,这篇题解希望通过一道简单的例题学会一种新的思想——推公式。
先看一下暴力的代码吧
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
int T;
cin >> T;
while(T -- )
{
int x;
cin >> x;
int y = 2 * x;
int sum = 0;
for(int i = min(x, y); i <= max(x, y); i ++ ) sum += i;
cout << sum << endl;
}
return 0;
}
这里进行了一些小小的优化,无论是负数还是正数,我们都是找到最小的值遍历到大的值,所以取代了不必要的判断分支。
推公式思想
当面对某些当面对某些算法问题时,使用数学推导或公式的思想可以帮助我们快速找到解决方案或优化算法的方法。以下是一些适合使用推公式思想解决问题的情况:
-
等差数列或等比数列求和:如果问题涉及到对一系列数字求和,而这些数字之间存在等差或等比关系,那么可以使用相应的求和公式快速计算结果。
-
累加求和:当需要计算从某个起点到终点的连续整数的和时,可以使用高斯求和公式
n * (n + 1) / 2
。这个公式可以直接给出求和结果,而无需实际进行循环累加操作。 -
组合数学问题:在组合数学问题中,经常需要计算排列组合的个数。这时可以使用组合数公式,如二项式系数
(n choose k)
的计算公式n! / (k! * (n-k)!)
,其中n!
表示阶乘。 -
算法优化:在某些情况下,通过数学推导可以优化算法的时间复杂度或空间复杂度。例如,通过数学特性或性质,可以将问题转化为更简单的形式,减少计算量或避免重复计算。
-
概率问题:在涉及概率和统计的问题中,数学公式和推导可以帮助我们计算概率、期望值、方差等。
当然,并非所有的算法问题都可以通过推导公式来解决,但在一些特定的情况下,数学推导可以提供洞察力和优化方向,帮助我们更高效地解决问题。在解决算法问题时,灵活运用数学推导和公式思想,结合适当的算法设计和数据结构选择,可以提高算法的效率和性能。
这道题是一道很基础的等差数列求和问题,如果想计算从 N
到 2*N
(包含边界)之间所有整数的和,可以使用以下公式:
c = (N + 2*N) * (N + 1) / 2
这个公式是根据等差数列求和公式推导而来。等差数列的首项是 N
,末项是 2*N
,共有 (2*N - N + 1) = N + 1
个元素。将这些值代入等差数列求和公式 (首项 + 末项) * 项数 / 2
,即可得到从 N
到 2*N
之间所有整数的和。
这里是推公式的代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
int T;
cin >> T;
while(T --)
{
int x;
cin >> x;
x = (abs(x) + 1) * x * 3 / 2; // 3x => (x + 2*x) 是首项加末项 abs(x) + 1 是项数
cout << x << endl;
}
return 0;
}