【蓝桥杯真题】平方差
·
问题

分析:
这个题要求求出在指定区域内的有多少个整数满足式子——两个整数的平方差
这个题如果按照正常思路分析,这两个整数肯定不会大于它本身的,所以遍历就好了
但时间复杂度太大了,要嵌套三个for循环
——
所以只能另想他法。
我们观察这个平方差的式子是不是可以化成——(a-b)(a+b)
a和b为整数,说明要么是偶数,要么是奇数
当两个同为偶数时,a-b和a+b也为偶数,两个偶数相乘——》为四的倍数(2k乘以2k)
当两个同为奇数时,a-b和a+b为偶数,同上。
如果一个为奇数一个为偶数,a-b和a+b都为奇数,则结果也为奇数
所以得出结论——
平方差的结果要么是四的倍数要么是奇数。
所以只需要在给定范围内判断是不是四的倍数或是奇数就行。
然后开始写代码,准备ac,但——发现时间好像还是超了?
那要再怎么优化呢?
可以直接利用式子算出一个区域里的奇数个数和4的倍数的个数(注意下面长的很像1但比1要长一点的其实是L)
-
计算区间内奇数数量:
- 公式:
奇数数量 = (r + l) / 2 - l / 2 - 例如,区间[3,7]中奇数为3,5,7,共3个。代入公式得:
(7+1)/2 - 3/2 = 4 - 1 = 3。
- 公式:
-
计算被4整除的数量:
- 公式:
被4整除的数量 = r / 4 - (l - 1) / 4 - 例如,区间[4,12]中被4整除的数为4,8,12,共3个。代入公式得:
12/4 - (4-1)/4 = 3 - 0 = 3。
- 公式:
具体公式解释:
奇数数量 = (r + l) / 2 - l / 2
被4整除的数量 = r / 4 - (l - 1) / 4
这两个公式,相信有很多人不理解,这里多解释一下:
奇数的计算原理
奇数的分布规律是每隔一个数出现一次。例如:
- 对于范围
[1, r],奇数数量为(r + 1) / 2。例如r=5时,奇数数量为(5+1)/2=3(即1, 3, 5)。 - 对于范围
[1, l-1],奇数数量为l / 2。例如l=3时,l-1=2,奇数数量为2/2=1(即1)。 - 区间
[l, r]的奇数数量即为两者之差:(r + 1)/2 - l/2。例如[3, 5]的奇数为3和5,共2个,计算为(5+1)/2 - 3/2 = 3 - 1 = 2。
四的倍数的计算原理
四的倍数的数量可直接通过整数除法计算:
- 对于范围
[1, r],四的倍数数量为r / 4。例如r=8时,四的倍数数量为8/4=2(即4, 8)。 - 对于范围
[1, l-1],四的倍数数量为(l-1) / 4。例如l=5时,l-1=4,四的倍数数量为4/4=1(即4)。 - 区间
[l, r]的四的倍数数量为两者之差:r/4 - (l-1)/4。例如[5, 8]的四的倍数为8,计算为8/4 - 4/4 = 2 - 1 = 1。
是否适用于其他的倍数?
是的。对于任意整数k,计算区间[l, r]内k的倍数的数量,通用公式为:
count_k = r / k - (l - 1) / k
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
long long l,r;
int main()
{
scanf("%lld%lld",&l,&r);
long long count_odd = (r + 1) / 2 - l / 2;
long long count_div4 = r / 4 - (l - 1) / 4;
printf("%lld",count_odd+count_div4);
return 0;
}
总结:
关键点总结
-
数学推导替代暴力枚举
将问题转化为对数的奇偶性和模 4 性质的分析,避免了嵌套循环的O(n)时间复杂度。 -
公式优化复杂度
直接通过数学公式计算区间内奇数和 4 的倍数的数量,时间复杂度从O(R-L+1)优化至O(1),可处理L, R极大(如1e18)的情况。 -
边界处理技巧
- 计算奇数时用
(R+1)/2而非R/2,确保右端点包含。 - 计算 4 的倍数时用
(L-1)/4排除左端点的左侧干扰。
- 计算奇数时用
更多推荐


所有评论(0)