首页 > 编程语言 >程序设计实习2023复习

程序设计实习2023复习

时间:2023-06-18 12:22:22浏览次数:43  
标签:le 复习 2023 算法 概率 哈希 delta 程序设计 mathrm

还没写完。


这个东西也许和 OI 有关?反正也要复习,干脆写篇博客。

introduction

传统算法设计一般考虑有效算法(多项式时间),以及追求“精确解”,尤其是“经典”算法或者数据结构。这节课一般考虑那些不那么传统的、更加偏向现代的算法设计。

一种就是近似算法,比如探索 NP-hard 问题在多项式时间内可以近似到多么精确,或者是本来存在多项式时间算法的问题,能否使用近似解改良复杂度。

对于最小化问题,一般使用近似比来衡量一个解的质量,如果对于某个输入 \(I\),你得到的解为 \(\mathrm{ALG}(I)\) 而最优解为 \(\mathrm{OPT}(I)\),那么我们可以通过 \(\max_{I}\frac{\mathrm{ALG}(I)}{\mathrm{OPT}(I)}\) 来衡量你给出的解的质量,这个值的取值范围显然是 \([1,+\infty)\),越小说明质量越好。

称该算法是 \(\alpha-\) 近似的,当对任意 \(I\),都有 \(\mathrm{ALG}(I)\le \alpha \cdot \mathrm{OPT}(I)\)。

例如 TSP 问题(旅行商问题,就是经过所有点并且回到出发地的最短长度),找到最小生成树上的最优解就是一个 \(2-\) 近似算法;找平面点集直径随便选择一个点然后找到离这个点最远的也是一个 \(2-\) 近似算法。

另一种意义上的近似是算法本身具有随机性,对于确定的输入得到随机的输出,比如有一定概率出错,但是不出错时有很好的性能保证。

近似 + 随机是现代算法设计的大趋势。

random

随机数

要在程序中生成随机数,可以考虑 C++ 中的 random 库,预设的几个标准随机数生成器如基于线性同余的 minstd_rand0minstd_randknuth_b,基于 Mersenne Twister 的 mt19937 ,还有基于 Lagged Fibonacci 的 ranlux24ranlux48,一般使用 minstd_rand 就行了。

然后还有从很多不同的特殊分布中采样,例如均匀独立采样 uniform_int_distributionuniform_real_distribution 分别是在一个区间里面均匀采整数或者实数,其他例如两点分布的 bernoulli_distribution 以 \(p\) 的概率取 \(1\) 其余取 \(0\),还有二项分布 binomial_distribution ,另外一个较常用到的是正态分布(高斯分布) normal_distribution

例如下面程序可以生成 \(10\) 个从标准正态分布 \(\mathcal{N}(0,1)\) 中的采样。

#include<random>
using namespace std;
int main(){
    std::minstd_rand gen(114514);
    std::normal_distribution<double> dis(0.0,1.0);
    for(int i=1;i<=10;++i)
        printf("%.5lf\n",dis(gen));
    return 0;
}

而更加一般的离散分布采样就是 discrete_distribution ,例如下图:

#include<random>
using namespace std;
int main(){
    std::minstd_rand gen(114514);
    std::discrete_distribution<> dis({1,4,6,4,1});
    for(int i=1;i<=10;++i)
        printf("%d\n",dis(gen));
    return 0;
}

这里传入的参数是一个长度为 \(n\) 的数组 \(a\),下标从 \(0\) 到 \(n-1\),其中 \(i\) 数字生成的概率为 \(\frac{a_i}{\sum_{j=0}^{n-1}a_j}\)。

随机算法

考虑一个随机算法,如果有 \(\delta\) 的出错概率,也就是说正确概率为 \(1-\delta\),如果算法只需要运行一次 \(\delta\) 取足够小的常数就行了,如果要多次运行且每次成功,可能就需要让 \(\delta\) 与运行次数相关。如果运行 \(q\) 次且每次失败概率为 \(\delta\),根据 Union Bound \(\mathrm{Pr}[\bigcup_i X_i]\le \sum_i \mathrm{Pr}[X_i]\),那么存在一次失败概率至多 \(q\delta\)。

算法具体分析的时候也许需要用到各种理论推导得出需要运行的次数,但是实际上只要试试够用就行了。

一些典型随机算法

测试矩阵相乘结果是否正确

给定三个 \(n\times n\) 的矩阵 \(A,B,C\),问是否有 \(AB=C\)。

考虑生成一个长度为 \(n\) 的随机向量 \(x\),每个值从集合 \(\{0,1\}\) 中等概率选取,如果 \(AB=C\) 那么必须有 \(ABx=Cx\),如果 \(AB\ne C\),那么考虑 \(AB\) 和 \(C\) 中至少有一列不完全相同,不妨假设是第 \(t\) 列,先确定 \(x\) 其他位置的值,然后考虑 \(t\) 位置的值,容易发现 \(t=0\) 和 \(t=1\) 中至少有一个会导致 \(ABx\ne Cx\),所以可以看出此时 \(ABx\ne Cx\) 的概率不低于 \(0.5\)。

重复随机 \(T\) 次,那么容易发现出错概率不超过 \(0.5^T\),更一般地,如果有一次出错概率 \(p\le 0.5\),那么 \(T\) 次都出错的概率就是 \(p^T\),要有 \(\delta\) 的出错概率或者说 \(1-\delta\) 的成功率就只需要有 \(T=O(\log (1/\delta))\) 即可。

\(\delta\) 取常数的话这个算法便可以做到 \(O(n^2)\) 判断。

Median Trick

现在有⼀个⿊盒能以 \(p>0.5\) 的概率正确回答某个 Yes/No 问题的答案,能否将其强化成任意的 \(1-\delta\)?

同样的,重复随机 \(T\) 次,取出现次数较多的作为答案,要选多大才行?

Chernoff Bound:设独立随机变量 \(X_1,\dots,X_n\in [0,1]\),令 \(X=\sum_{i=1}^nX_i,\mu=\mathrm{E}[X]\),则对 \(t\in [0,1]\) 有 \(\mathrm{Pr}[|X-\mu|\ge t\mu]\le 2\exp(-t^2\mu/3)\)。

随机 \(T\) 次回答正确次数期望时 \(pT\),所以也就要使得 \(\mathrm{Pr}[|X-pT|\ge (p-0.5)T]\le \delta\),视 \(p\) 为常数容易发现 \(T\) 取到 \(O(\log (1/\delta))\) 即可。

Hoeffding inequality:设独立随机变量 \(X_1,\dots,X_n\in [a,b]\),令 \(X=\sum_{i=1}^nX_i,\mu=\mathrm{E}[X]\),则对任意 \(t\) 有 \(\mathrm{Pr}[X-\mu\ge t]\le 2\exp\left(-\frac{2t^2}{n(b-a)^2}\right)\)。

recursion(递归)

这里是介绍经典算法,没啥好说的()

hash

哈希算法

\(h:[n]\to[m]\) 是随机哈希,指对于每个 \(i\in [n]\),有 \(h(i)\) 是 \([m]\) 上的均匀随机分布。一般要求是对于 \(i\ne j\),有 \(\mathrm{Pr}[h(i)=h(j)]\le 1/m\),其中每个 \(j\in [m]\) 称为 bucket。

考虑分布式环境的负载均衡问题,有 \(n\) 个请求要丢给 \(m\) 台服务器处理,如何使得每台服务器处理的请求个数尽量平均?可以使用上面讲到的随机哈希。

那么如果需要新增服务器呢?重构哈希函数太麻烦。

可以使用一致性哈希算法:构造一个足够大的哈希函数 \(h:\mathrm{int} \to \mathrm{int}\),然后把请求和服务器都哈希一下到一个环上,然后每个请求丢给这个环上对应后面第一个服务器做,只需要一个支持增删和查询后继操作的有序表即可。可以证明大概率负载均衡。

Count-min Sketch

考虑这样一个问题:输入 \(N\) 个 \([n]\) 上的整数,输入结束后给定 \(i\),要求近似回答 \(i\) 出现的次数。

Count-min Sketch 是一个数据结构,支持对于任意的误差参数 \(\epsilon\in (0,1)\),满足插入 \(N\) 个 \([n]\) 上的元素后给定 \(x\in[n]\) 查询 \(x\) 共出现多少次,设 \(\tilde{C}\) 表示估计量,\(C\) 表示真实量,可以以大概率(\(1-1/\mathrm{poly}(n)\) 的概率)满足 \(C\le \tilde{C}\le C+\epsilon\cdot N\)。

空间使用 \(\frac{\mathrm{poly}\log n}{\epsilon}\),且单次查询和插入单个元素的时间为 \(\frac{\mathrm{poly}\log n}{\epsilon}\)。

大体思路就是设置一个随即哈希函数 \(h:[n]\to [m]\),然后对每一个 \(j\in [m]\) 统计 \(C[j]\) 为满足 \(h(x)=j\) 的数量。容易发现如果不存在哈希冲突最后 \(C[h(x)]\) 就是 \(x\) 出现次数,如果出现冲突那么 \(C[h(x)]\) 只会更大。

设 \(x\) 真实出现次数为 \(C_x\),那么有:

\[\begin{aligned} \mathrm{E}[C[h(x)]]&=\mathrm{E}\left[C_x+\sum_{y\ne x,h(y)=h(x)}C_y\right]\\ &=C_x+\sum_{y\ne x,h(y)=h(x)}C_y\\ &=C_x+\sum_{y\ne x}\mathrm{Pr}[h(x)=h(y)]C_y\\ &\le C_x+N/m \end{aligned} \]

Markov inequality:若 \(X\ge 0\),有 \(\mathrm{Pr}[X\ge a]\le \mathrm{E}[X]/a\)。

对 \(C[h(x)]-C_x\) 用 Markov inequality,有 \(\mathrm{Pr}[C[h(x)]-C_x> \epsilon\cdot N]\le \frac{N/m}{\epsilon\cdot N}\le \frac{1}{\epsilon m}\),这里令 \(m\) 取 \(\frac{2}{\epsilon}\) 即可得到 \(0.5\) 的概率满足条件。

由于 \(C[h(x)]\) 总是高估,可以多次实验取最小值,每次至少 \(0.5\) 概率满足条件,所以独立运行 \(O(\log n)\) 次即可以 \(1-1/\mathrm{poly}(n)\) 的概率满足条件。

所以整体思路就是设置 \(T=O(\log n)\) 个独立随机哈希 \(h^{(i)}:[n]\to [m]\),其中 \(m=2/\epsilon\),并初始化 \(T\) 个 \(m\) 元 counter,然后插入删除元素就在每个 counter 里面都做就行了,查询就返回所有 counter 对应位置的最小值。

并且可以发现由于我们仅仅只是统计了元素数量,所以 count-min sketch 是可以接受相加相减的。

Count-min Sketch 应用

考虑 k-Heavy hitter(k-HH) 问题:给定长度为 \(N\) 的在 \([n]\) 上的数组,求出现次数前 \(k\) 多的元素。这个问题的应用例如用来查找那些异常流量或者访问较多的页面。

近似 k-HH 问题:你需要找到所有出现至少 \(N/k\) 次的元素,并且你还可以返回其他元素,返回的其他元素出现不少于 \(N/k-\epsilon N\) 次。

基于 count-min 的方法做数据流上的近似 k-HH,直接使用 count-min sketch 来存每个元素出现次数就行了,每次新加一个元素就查一下出现次数看是否满足条件即可,你找到的所有元素数量大概率是不超过 \(k\) 的,所以直接用表记录这些元素即可,动态增加 \(N\) 也没有任何问题。

标签:le,复习,2023,算法,概率,哈希,delta,程序设计,mathrm
From: https://www.cnblogs.com/lsq147/p/17488961.html

相关文章

  • 铁矿石 20230618
    先说结论下周阻力832.5-840。周初还是强势第5浪还没走完。   ......
  • 2023洗发护发市场分析(头皮清洁护理等新兴品类销售数据分析)
    如今,随着人们消费观念的转变,对洗发护发相关用品的要求也逐渐提高,由原来单一的清洁功能到更注重洗发护发用品的功能及护理效果。因此,洗发护发产品的品类不断增加,洗发护发产品的市场规模也不断扩大,整体趋于稳定发展。根据鲸参谋电商数据分析平台的相关数据显示,2023年1月至4月,天猫平台......
  • 纯碱波浪 20230618
    日线ABC的调整可能结束了。反弹看1780-1810一线。  下周初方案一: 方案二: ......
  • 2023-06-18 亚布力中国企业家论坛(山西)
     虽然有点看不上 王石。。。但是,王石说的,房地产企业未来的方向,参照日本房地产大公司的转型,从房地产为主、到服务为主 回到我们软件行业;软件的本质是服务;提高商业效率、增加商业能效、减少商业成本、为商业主航道保驾护航 企业降本增效,不擅长的东西,都走外包,提供外包服务......
  • SummerResearch_Log_20230617
    WorkingContent:1.今天还是读代码,对于代码有以下问题:(1)FCNet最后的输出层只有1个神经元,这如何做分类?——解决了,应该是因为它每个子任务都是训练两类,所以只需要一个神经元确定是哪个类别。(2)CIFAR数据集的分任务是什么情况?既使用了CIFAR10也使用了CIFAR100,并且分类的情况也有点......
  • 2023全国卷乙卷文科数学Word解析版
    2023全国卷乙卷理科数学解析版,Word版本。前言真题图片相关下载2023年高考全国乙卷理科数学真题版+解析版,......
  • 2023-06-18 as运行android项目报错:
    完整报错:Aproblemoccurredconfiguringrootproject'项目名'.>Couldnotresolvealldependenciesforconfiguration':classpath'.>Usinginsecureprotocolswithrepositories,withoutexplicitopt-in,isunsupported.Switch......
  • 2023冲刺国赛模拟20
    2023冲刺国赛模拟20越来越废物了。A.树染色\(f_{x,1/0}\)表示考虑\(x\)子树内,第一条链为黑色/白色,不考虑第一条链在子树外方案数的答案。转移枚举第一条链是哪个,用组合数给各个子树的链定序。code#include<bits/stdc++.h>usingnamespacestd;typedeflonglong......
  • 2023安洵杯—3D_maze
    3D_maze迷宫问题关键找迷宫结合移动以及最终的提示输出判断v5为左右移动,v4为上下移动,v3为跳到其他层,这是一个三维的迷宫,并且是一个此时能够得知是10×10×n,n还不清楚,不过代码中v3出现的最大值为5,此时推测n为6,也就是有6层,双击unk这个数组将数据提取出来发现有2400个,此时想到......
  • 数据结构课程设计2023夏7-4 先序和中序构造二叉树
    本题目要求用先序序列和中序序列构造一棵二叉树(树中结点个数不超过10个),并输出其后序序列。输入格式:在第一行中输入元素个数。第二行中输入先序序列,用空格分隔。第三行中输入中序序列,用空格分隔。输出格式:输出此二叉树的后序序列,用空格分隔,最后也有一个空格。输入样例:......