2025西安交大集训Day1:二分,三分,哈希,高精度,位运算,模拟退火
2025西安交大集训Day1:二分,三分,哈希,高精度,位运算,模拟退火
二分
详见2025dsfz集训Day2:二分与三分,三分在当前文章内已经重构过。
三分
三分算法详细解释
三分算法(Ternary Search)是一种用于在单峰函数(即函数在某一点左侧单调递增,右侧单调递减,或者相反)上寻找极值(最大值或最小值)的算法。它的基本思想是通过不断缩小搜索范围来逼近极值点。
算法步骤:
- 确定搜索范围:首先确定一个区间 \([left, right]\),确保极值点在这个区间内。
- 计算中间点:将区间分为三部分,计算两个中间点 \(mid1\) 和 \(mid2\):
- \(mid1 = left + (right - left) / 3\)
- \(mid2 = right - (right - left) / 3\)
- 比较函数值:比较 \(f(mid1)\) 和 \(f(mid2)\) 的大小:
- 如果 \(f(mid1) < f(mid2)\),则极值点在 \([left, mid2]\) 区间内,更新 \(right = mid2\)。
- 如果 \(f(mid1) > f(mid2)\),则极值点在 \([mid1, right]\) 区间内,更新 \(left = mid1\)。
- 如果 \(f(mid1) == f(mid2)\),则极值点在 \([mid1, mid2]\) 区间内,更新 \(left = mid1\) 和 \(right = mid2\)。
- 重复步骤2和3:直到区间 \([left, right]\) 足够小,或者达到预定的精度要求。
- 返回结果:返回 \((left + right) / 2\) 作为极值点的近似值。
举例说明:
假设我们有一个凹函数 \(f(x) = (x - 3)^2\),我们希望在区间 \([0, 6]\) 上找到最小值。
- 初始区间 \([left, right] = [0, 6]\)。
- 计算 \(mid1 = 0 + (6 - 0) / 3 = 2\),\(mid2 = 6 - (6 - 0) / 3 = 4\)。
- 计算 \(f(mid1) = (2 - 3)^2 = 1\),\(f(mid2) = (4 - 3)^2 = 1\)。
- 由于 \(f(mid1) == f(mid2)\),更新 \(left = 2\),\(right = 4\)。
- 重复步骤2和3,直到区间足够小。
最终,我们会发现最小值出现在 \(x = 3\)。
凹函数求最小值的模板代码
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
// 定义凹函数 f(x) = (x - 3)^2
double f(double x) {
return (x - 3) * (x - 3);
}
// 三分算法求解凹函数最小值
double ternary_search(double left, double right, double eps) {
while (right - left > eps) {
double mid1 = left + (right - left) / 3;
double mid2 = right - (right - left) / 3;
if (f(mid1) < f(mid2)) {
right = mid2;
} else {
left = mid1;
}
}
return (left + right) / 2;
}
int main() {
double left = 0.0;
double right = 6.0;
double eps = 1e-6; // 精度要求
double result = ternary_search(left, right, eps);
cout << "最小值出现在 x = " << fixed << setprecision(6) << result << endl;
cout << "最小值为 f(x) = " << fixed << setprecision(6) << f(result) << endl;
return 0;
}
代码解释:
- 函数 \(f(x)\):定义了我们要最小化的凹函数 \(f(x) = (x - 3)^2\)。
- \(ternary_search\) 函数:实现了三分算法,通过不断缩小搜索范围来逼近最小值点。
- \(main\) 函数:设置初始搜索区间 \([0, 6]\) 和精度要求 \(eps = 1e-6\),调用 \(ternary_search\) 函数并输出结果。
输出结果:
最小值出现在 x = 3.000000
最小值为 f(x) = 0.000000
这个结果与我们的预期一致,最小值出现在 \(x = 3\),最小值为 \(0\)。
哈希
详见我的字符串哈希学习笔记。
位运算
没啥好说的。
模拟退火
- 玄学算法会不了一点
习题
T1.P1883 【模板】三分 | 函数
- 多个2次函数在同一个平面直角坐标系上的图像的最上面的值可以抽象成一个坡度。直接三分找最小值即可。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int t, n, a[N], b[N], c[N];
double f(double x, int i) {
return x * x * a[i] + x * b[i] + c[i];
}
double check(double x) {
double ans = f(x, 1);
int i, j, k;
for (i = 2; i <= n; i++)
ans = max(ans, f(x, i));
return ans;
}
void work( ) {
cin >> n;
int i, j, k;
for (i = 1; i <= n; i++)cin >> a[i] >> b[i] >> c[i];
double l = 0, r = 1000, emp = 1e-11, mid1, mid2;
while (r - l > emp) {
mid1 = l + (r - l) / 3.0;
mid2 = r - (r - l) / 3.0;
if (check(mid1) > check(mid2))l = mid1;
else r = mid2;
}
printf("%.4lf\n", check(l));
}
int main( ) {
int t;
cin >> t;
while (t--) work();
}
T2.P1601 A+B Problem(高精)
- 朴素高精度
#include<bits/stdc++.h>
using namespace std;
int a[1000001],b[1000001],c[1000001],j;
bool x=false;
char s[1000001],ss[1000001];
int main() {
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
scanf("%s%s",s,ss);
a[0]=strlen(s);
b[0]=strlen(ss);
for(int i=1; i<=a[0]; i++) a[i]=s[a[0]-i]-'0';
for(int i=1; i<=b[0]; i++) b[i]=ss[b[0]-i]-'0';
for(j=1; j<=max(a[0],b[0])+1; j++) {
c[j]=a[j]+b[j];
if(c[j]>=10) {
c[j]%=10;
a[j+1]++;
}
}
c[0]=j;
if(c[j+1]>0) c[0]++;
for(int i=c[0]; i>=1; i--) {
if(x==false&&c[i]==0) continue;
x=true;
cout<<c[i];
}
if(x==false) cout<<0;
printf("\n");
return 0;
}
T3.P3370 【模板】字符串哈希
- 哈希map板子题
//哈希做法
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int t, n, a[N], b[N], c[N];
double f(double x, int i) {
return x * x * a[i] + x * b[i] + c[i];
}
double check(double x) {
double ans = f(x, 1);
int i, j, k;
for (i = 2; i <= n; i++)
ans = max(ans, f(x, i));
return ans;
}
void work( ) {
cin >> n;
int i, j, k;
for (i = 1; i <= n; i++)cin >> a[i] >> b[i] >> c[i];
double l = 0, r = 1000, emp = 1e-11, mid1, mid2;
while (r - l > emp) {
mid1 = l + (r - l) / 3.0;
mid2 = r - (r - l) / 3.0;
if (check(mid1) > check(mid2))l = mid1;
else r = mid2;
}
printf("%.4lf\n", check(l));
}
int main( ) {
int t;
cin >> t;
while (t--) work();
}
//map做法,代码少得离谱(bushi
#include <bits/stdc++.h>
using namespace std;
map <string,int> mp;
int n;
int main(){
cin>>n;
string s;
for(int i = 1;i <= n;i++){
cin>>s;
mp[s]++;
}
cout<<mp.size()<<endl;
}
T4.平衡点 / 吊打XXX
- 模拟退火。我也不会
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
constexpr int N = 10005;
int n, x[N], y[N], w[N];
double ansx, ansy, dis;
double Rand() { return (double)rand() / RAND_MAX; }
double calc(double xx, double yy) {
double res = 0;
for (int i = 1; i <= n; ++i) {
double dx = x[i] - xx, dy = y[i] - yy;
res += sqrt(dx * dx + dy * dy) * w[i];
}
if (res < dis) dis = res, ansx = xx, ansy = yy;
return res;
}
void simulateAnneal() {
double t = 100000;
double nowx = ansx, nowy = ansy;
while (t > 0.001) {
double nxtx = nowx + t * (Rand() * 2 - 1);
double nxty = nowy + t * (Rand() * 2 - 1);
double delta = calc(nxtx, nxty) - calc(nowx, nowy);
if (exp(-delta / t) > Rand()) nowx = nxtx, nowy = nxty;
t *= 0.9999;
}
for (int i = 1; i <= 1000; ++i) {
double nxtx = ansx + t * (Rand() * 2 - 1);
double nxty = ansy + t * (Rand() * 2 - 1);
calc(nxtx, nxty);
}
}
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
srand(1145); // 注意,在实际使用中,不应使用固定的随机种子。
std::cin >> n;
for (int i = 1; i <= n; ++i) {
std::cin >> x[i] >> y[i] >> w[i];
ansx += x[i], ansy += y[i];
}
ansx /= n, ansy /= n, dis = calc(ansx, ansy);
simulateAnneal();
std::cout << std::fixed << std::setprecision(3) << ansx << ' ' << ansy
<< '\n';
return 0;
}
2025西安交大集训Day1:二分,三分,哈希,高精度,位运算,模拟退火的更多相关文章
- 2019暑期金华集训 Day1 数据结构
自闭集训 Day1 数据结构 CF643G 用类似于下面的方法,搬到线段树上. 如何合并两个集合?先全部放在一起,每次删掉最小的\(cnt_i\),然后把其他所有的\(cnt\)都减去\(cnt_i\ ...
- 【欧拉回路+最小生成树】SD开车@山东2018省队一轮集训day1
目录 [欧拉回路+最小生成树]SD开车@山东2018省队一轮集训day1 PROBLEM 题目描述 输入 输出 样例输入 样例输出 提示 SOLUTION CODE [欧拉回路+最小生成树]SD开车@ ...
- 第二次组队赛 二分&三分全场
网址:CSUST 7月30日(二分和三分) 这次的比赛是二分&三分专题,说实话以前都没有接触过二分,就在比赛前听渊神略讲了下.......不过做着做着就对二分熟悉了,果然做题是学习的好方法啊~ ...
- 国庆集训 Day1 T2 生成图 DP
国庆集训 Day1 T2 生成图 现在要生成一张\(n\)个点的有向图.要求满足: 1.若有 a->b的边,则有 b->a 的边 2.若有 a->b 的边和 b->c 的边,则 ...
- 2019暑期金华集训 Day1 组合计数
自闭集训 Day1 组合计数 T1 \(n\le 10\):直接暴力枚举. \(n\le 32\):meet in the middle,如果左边选了\(x\),右边选了\(y\)(且\(x+y\le ...
- LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)
LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...
- [BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap)
[BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap) 题面 给出一个长度为n的字符串,m个操作,字符串仅包含小写英文字母 操作1:在k ...
- 牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并)
牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并) 题意:给你一颗树,要求找出简单路径上最大权值为1~n每个边权对应的最大异或和 题解: 根据异或的性质我们可以得到 \ ...
- 暑假集训Day1 整数划分
题目大意: 如何把一个正整数N(N长度<20)划分为M(M>=1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式. 输入格式: 第一行一个正整数T(T<= ...
- Java 对字符串数据进行MD5/SHA1哈希散列运算
Java对字符串数据进行MD5/SHA1哈希散列运算 [java] view plain copy package cn.aibo.test; import java.security.Message ...
随机推荐
- 玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之上传下载极速推进,纵享丝滑体验!
本文分享自天翼云开发者社区<玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之上传下载极速推进,纵享丝滑体验!>,作者:天翼云社区官方账号 随着传媒行业数字化转型驶入深水区,如何 ...
- FLink15--滑动窗口--SlidingWindiwApp
一.依赖 https://www.cnblogs.com/robots2/p/16048648.html 二.代码 概念:滑动窗口有两个参数,窗口大小20和滑动大小6,6秒滑一次,统计近20秒数据 前 ...
- Flink流式数据缓冲后批量写入Clickhouse
一.背景 对于clickhouse有过使用经验的开发者应该知道,ck的写入,最优应该是批量的写入.但是对于流式场景来说,每批写入的数据量都是不可控制的,如kafka,每批拉取的消息数量是不定的,fli ...
- mongoDb 的启动方式
参考地址:https://www.cnblogs.com/LLBFWH/articles/11013791.html 一. 启动 1. 最简单的启动方式,前台启动,仅指定数据目录,并且使用默认的271 ...
- CF895C Square Subsets 题解
看到 \(a_i\le 70\) 后,发现 \(n\) 啥用没有,因为只需要枚举 \(1-70\) 选几个即可. 看到求完全平方数后,想到分解质因数,由于 \(a_i\le 70\),所以只有 \(1 ...
- Netty实战:Netty优雅的创建高性能TCP服务器(附源码)
文章目录 前言 1. 前置准备 2. 消息处理器 3. 重写通道初始化类 4. 核心服务 5. 效果预览 6. 添加通道管理,给指定的客户端发送消息 7. 源码分享 前言 Springboot使用Ne ...
- Thymeleaf 在页面中直接显示内容
Thymeleaf 在页面中直接显示内容 一般情况下 Thymeleaf 模板要输出变量需要在某个标签中(如<div>.<span>)写th:text等属性来实现.但有时我 ...
- Deepseek学习随笔(5)--- DeepSeek 在职场中的应用
自动化办公 在职场中,DeepSeek 可以帮助自动化办公流程,如生成日报.撰写邮件等: 日报生成:请根据今日工作内容生成一份日报 DeepSeek 会生成一份简洁的工作日报,帮助你总结当天的工作内容 ...
- Windows 提权-SeBackupPrivilege 特权
本文通过 Google 翻译 Sebackupprivilege – Windows Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注 ...
- 使用Windows任务计划程序实现每天更换一张Processing创意桌面壁纸
Windows任务计划程序(Windows Task Scheduler)是Windows操作系统中的一项系统工具,它允许用户安排自动执行的任务.通过任务计划程序,用户可以设定特定的时间或条件来运行各 ...