杂谈 1:论 [l, r] 之间的非平方数

杂谈 1:论 [l,r] 之间的非平方数

Part 0 例题

先看一道例题;

给定两个数 l,r,求 lr 之间有多少个数不是平方数。平方数的定义:是一个数的平方。如 16 是平方数,因为 42=1611 则不是,因为 11 不为整数。数据范围:1l,r109

有些人一看到题目就像:“这不纯暴力吗?”。是的,大多数人看到题目的第一直觉是暴力。但是随着 l,r 的增大,暴力算法会跑得很慢,下面介绍几种算法来解决这个问题。

Part 1 纯暴力

直接枚举 [l,r] 区间,对于每个 i 判断 ii 是否为 0。(因为平方数开根是整数)如果是,计数器 +1。最后输出 rl+1 减去计数器里的数即可。

代码;

ll ans = 0;
for (int i = l; i <= r; ++ i) {
  if (sqrt(i) - int(sqrt(i)) == 0) {
    ++ ans;
  }
}
cout << (r - l + 1) - ans << '\n';

但是,这种算法的时间复杂度是 O(rl+1)。如果 rl+1 超过 108 会超时(注意,sqrt 函数也占用一定时间)。下面就介绍另一种算法。

Part 2 小暴力

这种算法属于暴力,但不是纯暴力。大概的思路就是:定义两个变量 A,B。从 l 开始,一个一个数枚举,找到 [l,r] 之间的最小的平方数并存进 A 里。再从 r 开始,一个一个数枚举,找到 [l,r] 之间的最大的平方数并存进 B 里。

如果两个都没找到(即 A=B=0),答案为 rl+1(因为 A=B=0 表示 [l,r] 之间没有平方数),否则答案为 (rl+1)(BA+1)(序列长度减去区间平方数,读者可自证为什么 BA+1[l,r] 之间的平方数个数)。

代码:

for (ll i = l; ; ++ i) {
  if (sqrt(i) - int(sqrt(i)) == 0) {
     A = sqrt(i);
     break;
   }
}
for (ll i = r; ; -- i) {
  if (sqrt(i) - int(sqrt(i)) == 0) {
     B = sqrt(i);
     break;
   }
}
if (!A && !B) {
  cout << r - l + 1 << '\n';
} else {
  cout << r - l + 1 - (B - A + 1) << '\n';
}

设离 l 最近的比 l 大的平方数是 A, 离 r 最近的比 r 小的平方数是 B,这种算法的时间复杂度是 O(Al+rB)。如果 Al 太远或 Br 太远就会 TLE。

Part 3 二分

我们可以发现,平方数满足单调性(1,4,9,16,25,36,),所以可以二分。

10931622,我们可以构造一个 031622 的平方数数组(ai=i2)。因此,我们可以二分在数组里找答案。找一个 L 使得 L2l,再找一个 R 使得 R2>r,答案就是 rl+1max(0, RL)(跟上个算法的思想差不多,读者可自证)。

代码:

const int kMaxN = sqrt(1e9);
for (int i = 1; i <= kMaxN; ++ i) {
  a[i] = i * i;
}
int L = 0, R = sqrt(1e9);
L = lower_bound(a, a + kMaxN, sqrt(l)) - a;
R = upper_bound(a, a + kMaxN, sqrt(r)) - a;
cout << r - l + 1 - max(0, R - L) << '\n';

这种算法的时间复杂度是 O(log109),还不够优秀。

Part 4 数学

A=llB=rr。那么 [l,r] 之间的平方数为 (A+1)2,(A+2)2,,(B1)2,B2。如果 A2=l,则答案为 (rl+1)(BA+1),否则答案为 (rl+1)(BA)。(跟 Part 2,3 的思想差不多,读者可自证)

代码:

int A = sqrt(l), B = sqrt(r);
cout << (A * A == l? r - l + 1 - B - A + 1 : r - l + 1 - B - A) << '\n';

时间复杂度 O(1),极为优秀。

posted @   beautiful_chicken233  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示