问题

分析:

这个题要求求出在指定区域内的有多少个整数满足式子——两个整数的平方差

这个题如果按照正常思路分析,这两个整数肯定不会大于它本身的,所以遍历就好了

但时间复杂度太大了,要嵌套三个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)

  1. 计算区间内奇数数量:

    • 公式:奇数数量 = (r + l) / 2 - l / 2
    • 例如,区间[3,7]中奇数为3,5,7,共3个。代入公式得:(7+1)/2 - 3/2 = 4 - 1 = 3。
  2. 计算被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;
}

总结:

关键点总结

  1. 数学推导替代暴力枚举
    将问题转化为对数的奇偶性和模 4 性质的分析,避免了嵌套循环的 O(n) 时间复杂度。

  2. 公式优化复杂度
    直接通过数学公式计算区间内奇数和 4 的倍数的数量,时间复杂度从 O(R-L+1) 优化至 O(1),可处理 L, R 极大(如 1e18)的情况。

  3. 边界处理技巧

    • 计算奇数时用 (R+1)/2 而非 R/2,确保右端点包含。
    • 计算 4 的倍数时用 (L-1)/4 排除左端点的左侧干扰。

更多推荐