2025西安交大集训Day1:二分,三分,哈希,高精度,位运算,模拟退火

二分

详见2025dsfz集训Day2:二分与三分,三分在当前文章内已经重构过。

三分

三分算法详细解释

三分算法(Ternary Search)是一种用于在单峰函数(即函数在某一点左侧单调递增,右侧单调递减,或者相反)上寻找极值(最大值或最小值)的算法。它的基本思想是通过不断缩小搜索范围来逼近极值点。

算法步骤:

  1. 确定搜索范围:首先确定一个区间 \([left, right]\),确保极值点在这个区间内。
  2. 计算中间点:将区间分为三部分,计算两个中间点 \(mid1\) 和 \(mid2\):
  • \(mid1 = left + (right - left) / 3\)
  • \(mid2 = right - (right - left) / 3\)
  1. 比较函数值:比较 \(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\)。
  1. 重复步骤2和3:直到区间 \([left, right]\) 足够小,或者达到预定的精度要求。
  2. 返回结果:返回 \((left + right) / 2\) 作为极值点的近似值。

举例说明:

假设我们有一个凹函数 \(f(x) = (x - 3)^2\),我们希望在区间 \([0, 6]\) 上找到最小值。

  1. 初始区间 \([left, right] = [0, 6]\)。
  2. 计算 \(mid1 = 0 + (6 - 0) / 3 = 2\),\(mid2 = 6 - (6 - 0) / 3 = 4\)。
  3. 计算 \(f(mid1) = (2 - 3)^2 = 1\),\(f(mid2) = (4 - 3)^2 = 1\)。
  4. 由于 \(f(mid1) == f(mid2)\),更新 \(left = 2\),\(right = 4\)。
  5. 重复步骤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;
}

代码解释:

  1. 函数 \(f(x)\):定义了我们要最小化的凹函数 \(f(x) = (x - 3)^2\)。
  2. \(ternary_search\) 函数:实现了三分算法,通过不断缩小搜索范围来逼近最小值点。
  3. \(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:二分,三分,哈希,高精度,位运算,模拟退火的更多相关文章

  1. 2019暑期金华集训 Day1 数据结构

    自闭集训 Day1 数据结构 CF643G 用类似于下面的方法,搬到线段树上. 如何合并两个集合?先全部放在一起,每次删掉最小的\(cnt_i\),然后把其他所有的\(cnt\)都减去\(cnt_i\ ...

  2. 【欧拉回路+最小生成树】SD开车@山东2018省队一轮集训day1

    目录 [欧拉回路+最小生成树]SD开车@山东2018省队一轮集训day1 PROBLEM 题目描述 输入 输出 样例输入 样例输出 提示 SOLUTION CODE [欧拉回路+最小生成树]SD开车@ ...

  3. 第二次组队赛 二分&三分全场

    网址:CSUST 7月30日(二分和三分) 这次的比赛是二分&三分专题,说实话以前都没有接触过二分,就在比赛前听渊神略讲了下.......不过做着做着就对二分熟悉了,果然做题是学习的好方法啊~ ...

  4. 国庆集训 Day1 T2 生成图 DP

    国庆集训 Day1 T2 生成图 现在要生成一张\(n\)个点的有向图.要求满足: 1.若有 a->b的边,则有 b->a 的边 2.若有 a->b 的边和 b->c 的边,则 ...

  5. 2019暑期金华集训 Day1 组合计数

    自闭集训 Day1 组合计数 T1 \(n\le 10\):直接暴力枚举. \(n\le 32\):meet in the middle,如果左边选了\(x\),右边选了\(y\)(且\(x+y\le ...

  6. LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set(线性基,贪心)

    LOJ 6060「2017 山东一轮集训 Day1 / SDWC2018 Day1」Set $ solution: $ 这一题的重点在于优先级问题,我们应该先保证总和最大,然后再保证某一个最小.于是我 ...

  7. [BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap)

    [BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap) 题面 给出一个长度为n的字符串,m个操作,字符串仅包含小写英文字母 操作1:在k ...

  8. 牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并)

    牛客2018国庆集训 DAY1 D Love Live!(01字典树+启发式合并) 题意:给你一颗树,要求找出简单路径上最大权值为1~n每个边权对应的最大异或和 题解: 根据异或的性质我们可以得到 \ ...

  9. 暑假集训Day1 整数划分

    题目大意: 如何把一个正整数N(N长度<20)划分为M(M>=1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式. 输入格式: 第一行一个正整数T(T<= ...

  10. Java 对字符串数据进行MD5/SHA1哈希散列运算

    Java对字符串数据进行MD5/SHA1哈希散列运算 [java] view plain copy package cn.aibo.test; import java.security.Message ...

随机推荐

  1. 第一届启航杯网络安全大赛部分wp

    第一届启航杯 WEB Easy include <?php error_reporting(0); //flag in flag.php $file=$_GET['fil e']; if(iss ...

  2. tomcat 自启动脚本(普通模式)

    tomcat daemon模式启停脚本 https://www.cnblogs.com/wxp100/p/14846331.html tomcat 普通模式启停脚本 vi tomcatServer.s ...

  3. pip安装MySQLdb报错mysql_config not found

    报错EnvironmentError: mysql_config not found解决方法 1.sudo apt-get install python-setuptools 2.sudo apt-g ...

  4. Atcoder ABC392F Insert 题解 [ 绿 ] [ 线段树二分 ] [ 倒序操作 ]

    Insert:绷不住了,ds 学傻了导致一直在写一个假的没边的做法,赛后 5min 胡出正解,唐. 思路 首先正着操作想想就觉得不太好搞,所以考虑一个经典 trick:单点正向加入操作转化为倒序删除操 ...

  5. [SCOI2016] 幸运数字 题解

    \(xor\) 最大值想到线性基,路径想到 \(lca\) 和树链剖分,由于没有修改用 \(lca\) 就可以.先用处理 \(fa\) 数组的方式处理倍增线性基(自然是得用线性基合并的),在求 \(l ...

  6. 福尼斯焊机TPS320i/TPS400i/TPS500i的焊接特性

    福尼斯焊机设备原理 TPS320i.TPS400i.TPS500i和TPS 600iMIG/MAG电源由微处理器控制,机器人驱动器维修,是完全数字化的逆变器电源. 模块化设计和系统的扩展潜力使其具有高 ...

  7. Redis高可用部署:3台服务器打造哨兵集群

    1.Redis集群介绍 Redis 集群(Redis Cluster)是Redis提供的一种分布式部署方式,旨在提供高可用性.如果某个主节点发生故障,集群能够自动进行故障转移,将副本提升为主节点,从而 ...

  8. 【Python】读取写入INI文件

    最近,写个abaqus的python脚本,需要输入的item比较多,而且也有一些不经常修改但又可能要修改的option.如果都用abaqus的getinput()和getinputs()函数,那输入的 ...

  9. SpringSecurity学习笔记-前后端分离

    1. 简介 Spring Security是Spring家族中的一个安全管理框架.相比于另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富. 一般来说中大型的项目都是使用Sp ...

  10. ModuleNotFoundError: No module named '_sqlite3' when Python3

    前言 运行 python 报错:ModuleNotFoundError: No module named '_sqlite3' 解决 重新编译安装 python ./configure --enabl ...