根号算法题库

前言

根号算法博大精深,决定在此收集。
例题我博客基本都能找到。

带根号算法

分块算法

一种是最普通的分块算法,把序列分块,然后可以解决区间问题。分块算法可以维护一些线段树维护不了的东西,例如单调队列等,线段树能维护的东西必须能够进行信息合并,而分块则不需要。不过,和线段树一样,分块需要支持类似标记合并的东西。
当然,为了使得速度不至于太慢,每一块的大小应该通过实验得知。即找到一个合理的块大小,使得在该大小下算法跑的比较快。
具体实现时,用belong[i]表示i所属块。对于修改操作,某一块全部要被修改,则更改它的信息。多余部分直接暴力修改,有些时候需要对多余部分所属块进行暴力重构(例如维护单调队列)。
例题:jzoj3167查税,用分块维护单调队列。去年五校联考第六场的第三题,用分块维护桶。bzoj2002弹飞绵羊,用分块维护答案。bzoj3809Gty的二逼妹子序列的一种算法中需要用到这种最普通的分块。jzoj4438K小数查询。

还有其他的分块,这类题目没有修改操作,但是要求询问的东西较难维护。其通常为预处理ans[i,j]表示第i块到第j块的答案,然后再预处理sum[i,j]表示前j块i元素的出现次数,然后对于一个询问,只对多余部分进行扫描,然后可以用一些数据结构维护。
又或者预处理第i块到第n块的答案诸如此类。都是没有修改,利用分块的题目。
例题:bzoj4241历史研究,bzoj3289Mato的文件管理,bzoj2821作诗,bzoj2724蒲公英,bzoj3744Gty的妹子序列,都属于这种类型。

但是其实运用数据结构维护信息,上面的所谓“无修改利用分块题目”也可以变成兹瓷修改操作。
例题:bzoj3787Gty的文艺妹子序列。

当然大家熟知的一种,就是离线进行处理的莫队算法,其思路在于对于l~r的答案如果我们可以通过维护而得到l~r+1或是l+1~r(也就是添加和删除),那么可以通过改变做询问的顺序来降低复杂度,将询问左端点所属块为第一关键字,右端点为第二关键字,排序,然后直接做。复杂度非常好证

### C++ 中实现开根号算法的方法 在 C++ 编程中,可以采用多种方式来实现开根号的功能。以下是几种常见的方法及其对应的代码示例。 #### 方法一:使用标准库 `sqrt` 函数 C++ 提供了 `<cmath>` 库中的 `sqrt` 函数用于快速计算平方根。这种方法简单高效,适合大多数场景。 ```cpp #include <iostream> #include <cmath> // 包含 sqrt 函数 int main() { double x = 4.0; double result = sqrt(x); std::cout << "4 的平方根是 " << result << std::endl; return 0; } ``` 该方法利用了标准库函数,无需额外编写逻辑即可完成开根号操作[^1]。 --- #### 方法二:基于雷神之锤 III 游戏的快速开方算法 这是一种经典的优化算法,最初由 John Carmack 在《Quake III Arena》游戏中提出。它通过运算牛顿迭代法相结合的方式实现了高效的平方根倒数近似计算。 ```cpp float Sqrt(float x) { if (x <= 0) return 0; const float xhalf = x * 0.5f; // 输入值的一半 int i = *(int*)&x; // 转换为整型存储形式 i = 0x1FBD1E2C + (i >> 1); // 近似公式调整 x = *(float*)&i; // 转回浮点型 x = x / 2 + xhalf / x; // 牛顿迭代一次 x = x / 2 + xhalf / x; // 再次迭代提高精度 return x; } ``` 这种算法的核心在于魔术数字 `0x1FBD1E2C` 操作 `(i >> 1)`,它们共同作用于初始猜测值的生成过程[^2]。 --- #### 方法:牛顿迭代法手动实现 如果希望完全不依赖外部库,则可以通过牛顿迭代法自行实现平方根功能。其基本原理是从某个初值出发逐步逼近真实解。 ```cpp std::pair<double, int> square(double x) { double guess = x; // 初值设为输入本身 int iterations = 0; // 记录迭代次数 while (fabs(guess * guess - x) > 1e-6) { // 设置收敛条件 guess = (guess + x / guess) / 2; // 更公式 ++iterations; } return {guess, iterations}; // 返回结果与迭代次数 } int main() { auto [result, count] = square(2.0); std::cout << "2 的平方根是 " << result << ", 经过 " << count << " 次迭代." << std::endl; return 0; } ``` 此方法不仅能够得到最终结果,还能统计所需的迭代步数以便分析性能表现[^3]。 --- #### 方法四:二分查找法求解平方根 对于某些特定需求(如教学目的),也可以考虑使用二分查找策略寻找满足误差范围内的解。 ```cpp double bsqrt(double x) { const double eps = 1e-6; // 定义允许的最大误差 double low = 0.0, high = x; // 初始化上下界 while (high - low > eps) { // 当区间宽度大于阈值时继续循环 double mid = (low + high) / 2.0; if ((mid * mid - x) >= eps) high = mid; // 若当值过大则缩小上限 else low = mid; // 否则增大下限 } return low; // 输出接近目标值的一个端点 } ``` 相比其他技术而言,这种方式更容易理解但也可能稍显低效[^5]。 --- #### 方法五:自定义输出格式化处理 当需要控制打印的小数数或者遵循特殊的数据展示规则时,可结合流操纵符定制显示效果。 ```cpp #include <iomanip> // 假定已知两点坐标分别为 A(x1,y1),B(x2,y2),需求数学意义上的欧几里得距离 double distanceBetweenPoints(double x1, double y1, double x2, double y2){ double dx = x1 - x2; double dy = y1 - y2; return sqrt(dx*dx + dy*dy); } int main(){ double px1=1.0 ,py1=2.0 ,px2=4.0 ,py2=6.0 ; double dist = distanceBetweenPoints(px1, py1, px2, py2); std::cout<<std::fixed<<std::setprecision(2)<<dist<<'\n'; return 0; } ``` 这里展示了如何借助 `<iomanip>` 头文件里的工具精确指定数值呈现样式[^4]。 --- ### 总结 以上介绍了五种不同的 C++ 平方根实现途径,各有优劣适用于不同场合。实际开发过程中应根据具体项目背景选取最合适的方案加以应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值