<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Lloyd的个人博客</title>
  <icon>https://files.seeusercontent.com/2026/04/23/hpM4/favicon.png</icon>
  <subtitle>更高更快更强更团结</subtitle>
  <link href="https://lloydkai.cn/atom.xml" rel="self"/>
  
  <link href="https://lloydkai.cn/"/>
  <updated>2026-04-23T01:47:23.470Z</updated>
  <id>https://lloydkai.cn/</id>
  
  <author>
    <name>Lloyd</name>
    <email>kai9827@outlook.com</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>hexo博客系列(五)博客部署</title>
    <link href="https://lloydkai.cn/posts/blog-series-five/"/>
    <id>https://lloydkai.cn/posts/blog-series-five/</id>
    <published>2026-04-09T09:11:35.000Z</published>
    <updated>2026-04-23T01:47:23.470Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/22/CkiLVJsDWjncZxw.jpg" alt></p><h1>工作流</h1><p>目前我的工作流是：本地<code>hexo d</code>推送部署到github上，然后通过github action部署到github pages 和vercel上。同时通过脚本将public文件夹下的静态文件同步推送到我的ECS服务器上。</p><p>也就是说，可以通过三个域名访问到我的博客，一个是<a href="https://lloyd-kai.github.io/">https://lloyd-kai.github.io/</a> 源站点，一个是<a href="https://blog.lloydkai.top/">https://blog.lloydkai.top/</a>  部署到vercel上的(我已解析为自己购买的域名)，一个是<a href="https://lloydkai.cn/">https://lloydkai.cn/</a>  部署到阿里云的ECS上的(方便国内的用户访问)。</p><h2 id="部署时参考的教程">部署时参考的教程</h2><h3 id="部署到vercel上">部署到vercel上</h3><p><a href="https://www.bilibili.com/video/BV1B4421X7kx/?share_source=copy_web&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">零成本免备案部署博客——vercel与zeabur搭建hexo主题博客</a> ,    <a href="https://www.bilibili.com/video/BV1Ke4y1v7Qr/?share_source=copy_web&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">第2期：Vercel部署并绑定自定义域名+安装Butterfly主题</a> 。这两个视频互相补充，主要参考第二个视频即可部署成功</p><h3 id="部署到gihub的pages上">部署到gihub的pages上</h3><p>请看<code>hexo博客系列(二)博客创建指南</code> ，严格来说我不是将hexo博客项目中所有的内容推送到github的，而是用hexo-deployer-git插件在本地生成public下的html文件，再推送到github pages上的。所以你会看到其他的的教程中它是先将整个hexo项目先推送到github，然后再将分支推送到github pages上，而我只上传必要的文件到github pages上，所有的文件都在我的本地电脑里面。主要的参考教程：<a href="https://www.fomal.cc/posts/e593433d.html">Fomalhaut的博客</a>，核心就在于<strong>是否下载了hexo-deployer-git插件以及配置ssh密钥等</strong>。</p><p><a href="https://hexo.io/zh-cn/docs/one-command-deployment">官方hexo-deployer-git教程</a></p><h3 id="部署到阿里云ECS上">部署到阿里云ECS上</h3><p>主要参考的教程：<a href="https://www.vgtmy.com/2025/05/26/%E5%8D%9A%E5%AE%A2%E9%83%A8%E7%BD%B2%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91-GitHub%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E5%85%A8%E6%B5%81%E7%A8%8B%E6%8C%87%E5%8D%97/#%E8%87%AA%E5%8A%A8%E7%BB%AD%E7%AD%BE%EF%BC%88Let%E2%80%99s-Encrypt%EF%BC%89">链接</a></p><p><strong>以下是根据我自己的实际使用情况修改</strong>，我购买的是阿里云的ECS服务器，ubuntu版本</p><p>二、安装和准备环境部分中的2. 连接你的阿里云服务器（使用 SSH）</p><p>没有上传SSH密钥之前要登录就用</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh -l root 你购买的ECS的公网IP -p 22</span><br></pre></td></tr></table></figure><p>再输入密码即可SSH远程登录(注意要在登录之前先再ECS中重置密码，自己设置)</p><p>等之后上传SSH密钥就可以使用下方的命令行远程登录</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh root@你购买的ECS的公网IP(比如192.168.240.243)</span><br></pre></td></tr></table></figure><hr><p>四、设置阿里云防火墙与安全组</p><p>如果要备案的话，注意停止你的域名解析。</p><hr><p>三、配置 Nginx 启用 HTTPS</p><p>这里的内容我修改为</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line">listen 80 default_server;</span><br><span class="line">listen [::]:80 default_server;</span><br><span class="line">server_name _;</span><br><span class="line"></span><br><span class="line">root /var/www/html;</span><br><span class="line">index index.html;</span><br><span class="line"></span><br><span class="line">location / &#123;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">listen 443 ssl;</span><br><span class="line">listen [::]:443 ssl;</span><br><span class="line">server_name 域名 www.域名;</span><br><span class="line">ssl_certificate /etc/nginx/ssl/域名.cn.pem;</span><br><span class="line">ssl_certificate_key /etc/nginx/ssl/.cn.key;</span><br><span class="line">root /var/www/html;</span><br><span class="line">index index.html;</span><br><span class="line"></span><br><span class="line">location / &#123;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>用快捷键ctrl+s保存,ctrl+x退出。</p><p>后面我就不用他的github action</p><hr><p>三、添加 GitHub Actions 工作流配置</p><p><strong>从这里开始我就没有采用他的方案了</strong></p><p>我的实现思路是：</p><ol><li>自定义 deployAfter 钩子执行 scp，把 public/* 上传到 ECS /var/www/html/</li><li>上传后自动修复目录与文件权限（目录 755，文件 644）</li><li>Nginx 直接托管 /var/www/html 的静态文件</li></ol><p>这样就无需借助github action，但是缺点就是以后hexo d推送的时候会比较慢，大概一分钟左右。</p><p>首先，先在<code>_config.yml</code> 文件中添加配置</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 本地执行 `hexo d` 后，自动通过 scp 上传到阿里云 ECS</span></span><br><span class="line"><span class="attr">ecs_deploy:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">host:</span> <span class="string">你的ECS公网IP</span></span><br><span class="line">  <span class="attr">user:</span> <span class="string">root</span></span><br><span class="line">  <span class="attr">target:</span> <span class="string">/var/www/html/</span></span><br></pre></td></tr></table></figure><p><strong>在hexo项目根目录下新建脚本 scripts/deploy-ecs.js</strong></p><p>文件内容如下（可直接使用）：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#x27;use strict&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> &#123; spawnSync &#125; = <span class="built_in">require</span>(<span class="string">&#x27;child_process&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">runOrThrow</span>(<span class="params">command, errorMessage</span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> result = <span class="title function_">spawnSync</span>(command, &#123;</span><br><span class="line">    <span class="attr">shell</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">stdio</span>: <span class="string">&#x27;inherit&#x27;</span>,</span><br><span class="line">    <span class="attr">cwd</span>: process.<span class="title function_">cwd</span>()</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (result.<span class="property">status</span> !== <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`<span class="subst">$&#123;errorMessage&#125;</span> (exit code <span class="subst">$&#123;result.status&#125;</span>)`</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">hexo.<span class="title function_">on</span>(<span class="string">&#x27;deployAfter&#x27;</span>, <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> cfg = hexo.<span class="property">config</span>.<span class="property">ecs_deploy</span> || &#123;&#125;;</span><br><span class="line">  <span class="keyword">if</span> (cfg.<span class="property">enable</span> === <span class="literal">false</span>) &#123;</span><br><span class="line">    hexo.<span class="property">log</span>.<span class="title function_">info</span>(<span class="string">&#x27;[ecs-deploy] disabled by config&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> host = cfg.<span class="property">host</span>;</span><br><span class="line">  <span class="keyword">const</span> user = cfg.<span class="property">user</span> || <span class="string">&#x27;root&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> target = cfg.<span class="property">target</span> || <span class="string">&#x27;/var/www/html/&#x27;</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (!host) &#123;</span><br><span class="line">    hexo.<span class="property">log</span>.<span class="title function_">warn</span>(<span class="string">&#x27;[ecs-deploy] skip: missing ecs_deploy.host in _config.yml&#x27;</span>);</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> source = <span class="string">&#x27;public/*&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> destination = <span class="string">`<span class="subst">$&#123;user&#125;</span>@<span class="subst">$&#123;host&#125;</span>:<span class="subst">$&#123;target&#125;</span>`</span>;</span><br><span class="line">  <span class="keyword">const</span> scpCommand = <span class="string">`scp -r <span class="subst">$&#123;source&#125;</span> <span class="subst">$&#123;destination&#125;</span>`</span>;</span><br><span class="line">  <span class="keyword">const</span> remoteFixPermsCommand = <span class="string">`ssh <span class="subst">$&#123;user&#125;</span>@<span class="subst">$&#123;host&#125;</span> &quot;find <span class="subst">$&#123;target&#125;</span> -type d -exec chmod 755 &#123;&#125; \\; ; find <span class="subst">$&#123;target&#125;</span> -type f -exec chmod 644 &#123;&#125; \\;&quot;`</span>;</span><br><span class="line"></span><br><span class="line">  hexo.<span class="property">log</span>.<span class="title function_">info</span>(<span class="string">`[ecs-deploy] uploading via scp: <span class="subst">$&#123;source&#125;</span> -&gt; <span class="subst">$&#123;destination&#125;</span>`</span>);</span><br><span class="line"></span><br><span class="line">  <span class="title function_">runOrThrow</span>(scpCommand, <span class="string">&#x27;[ecs-deploy] scp failed&#x27;</span>);</span><br><span class="line">  hexo.<span class="property">log</span>.<span class="title function_">info</span>(<span class="string">&#x27;[ecs-deploy] fixing file permissions for nginx&#x27;</span>);</span><br><span class="line">  <span class="title function_">runOrThrow</span>(remoteFixPermsCommand, <span class="string">&#x27;[ecs-deploy] permission fix failed&#x27;</span>);</span><br><span class="line"></span><br><span class="line">  hexo.<span class="property">log</span>.<span class="title function_">info</span>(<span class="string">&#x27;[ecs-deploy] upload finished&#x27;</span>);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>为什么要有权限修复：</p><ul><li>你这类 scp 上传在某些环境会导致目录权限变成 700</li><li>Nginx 无法读取 css/js/font 目录时，就会出现页面样式与 GitHub Pages 差异很大</li></ul><p>以后只需要正常在终端中输入以下命令</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo cl;hexo g;hexo d</span><br></pre></td></tr></table></figure><p>就可以同步将public下生成的静态文件直接传到ECS服务器上。</p><h2 id="自动续签SSL证书">自动续签SSL证书</h2><p><a href="https://www.vgtmy.com/2025/05/26/%E5%8D%9A%E5%AE%A2%E9%83%A8%E7%BD%B2%E5%88%B0%E9%98%BF%E9%87%8C%E4%BA%91-GitHub%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2%E5%85%A8%E6%B5%81%E7%A8%8B%E6%8C%87%E5%8D%97/#%E8%87%AA%E5%8A%A8%E7%BB%AD%E7%AD%BE%EF%BC%88Let%E2%80%99s-Encrypt%EF%BC%89">参考链接</a> ，使用了Let’s Encrypt自动续签，建议使用阿里云，每年免费额度有20个证书，有效时间为三个月，基本够用了。</p><p>SSL证书其实就是安全性的问题，如果没有签的话在访问网站的时候，浏览器就会显示</p><p><code>您与此网站之间建立的连接不安全,请勿在此网站上输入任何敏感信息（例如密码或信用卡信息），因为攻击者可能会盗取这些信息。 了解详情</code></p><p>自动续签时间是60天一次，一年大概就6个。如果需要就自己修改时间。</p><h2 id="如何备案">如何备案</h2><p><a href="https://help.aliyun.com/zh/icp-filing/basic-icp-service/getting-started/quick-start-for-icp-filing-for-personal-websites?spm=a2c4g.11186623.0.0.9afd55cfiW4cXr">官方文档</a></p><p>总体来说流程有五个——填表申请、阿里云初审、短信验证、管理审核、ICP出结果和公安备案，ICP出结果之后就要马上将备案信息添加到首页之下，包括公安的备案(出结果后30天内)，如果不添加就会有罚款。</p><p>官方表述</p><p><code>ICP备案成功后，您需要在网站首页底部悬挂ICP备案号并生成链接指向工信部网站(https://beian.miit.gov.cn/)，否则被相关部门核查出来，将会面临罚款。</code></p>]]></content>
    
    
    <summary type="html">具体讲解hexo的博客是如何部署到github pages,vercel和阿里云的ECS服务器上的</summary>
    
    
    
    <category term="blog" scheme="https://lloydkai.cn/categories/blog/"/>
    
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="blog" scheme="https://lloydkai.cn/tags/blog/"/>
    
    <category term="hexo" scheme="https://lloydkai.cn/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>Rust系列(一)Rust语言基础</title>
    <link href="https://lloydkai.cn/posts/rust-series-one/"/>
    <id>https://lloydkai.cn/posts/rust-series-one/</id>
    <published>2026-04-07T01:16:54.000Z</published>
    <updated>2026-04-23T02:21:13.774Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/22/JIZCAPigNfBVQTa.jpg" alt></p><h1>rust的安装</h1><h2 id="安装rust编译器及其IDE">安装rust编译器及其IDE</h2><p>官网：<a href="https://rust-lang.org/tools/install/">https://rust-lang.org/tools/install/</a>   网上下载init.exe文件然后点击，默认输入1并确认即可</p><p>IDE：推荐使用RustRover或者是用vscode+rust的插件，我这里用RustRover</p><h2 id="更新、卸载和查看rust版本">更新、卸载和查看rust版本</h2><p>更新</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rustup update</span><br></pre></td></tr></table></figure><p>卸载</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rustup self uninstall</span><br></pre></td></tr></table></figure><p>查看版本</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rustc --version</span><br></pre></td></tr></table></figure><p>查看本地文档</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rustup doc</span><br></pre></td></tr></table></figure><h1>初识rust</h1><p>rust对应程序文件的后缀名都是rs,文件的命名规范是小驼峰+_ 比如<code>hello_world.rs</code></p><h2 id="从hello-world开始">从hello world开始</h2><p>在main.rs中输入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">fn main()</span><br><span class="line">&#123;</span><br><span class="line">println!(&quot;hello world!&quot;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>解析</p><ul><li>main函数是每个rust可执行程序最先运行的代码</li><li>rust的缩进是四个空格</li><li><code>println!</code>是一个rust macro(宏),如果是函数的话就没有<code>!</code></li></ul><h2 id="简单的rust程序是如何编译的">简单的rust程序是如何编译的</h2><p>编译命令</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rustc main.rs</span><br></pre></td></tr></table></figure><p>就会生成main.exe的可执行文件还有一个main.pdb文件(包含调试信息)</p><p>而rustc编译只适合简单的项目，对于复杂的项目我们就需要一个<strong>构建系统和包管理的工具</strong>，在Python中是pip，在C语言中是gcc和cmake，而在rust中是<strong>Cargo</strong></p><p>如果要用cargo创建项目，就</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cargo new hello_cargo</span><br></pre></td></tr></table></figure><h2 id="cargo项目是如何编译的">cargo项目是如何编译的</h2><p>在RustRover中把大部分的编译细节都隐藏了，对于软件开发者来说是好事，但是rust应用最多的是操作系统内核和编译器中，需要经常在原始的条件下编译，这里将着重介绍cargo项目的编译过程，以便后续的项目开发</p><p><strong>创建可执行文件</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cargo build</span><br></pre></td></tr></table></figure><p>一般在<code>target/debug/</code>文件下面，生成exe文件</p><p><strong>运行cargo项目</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cargo run</span><br></pre></td></tr></table></figure><p>这个命令实现编译代码+执行结果，如果已经编译过且源码未改变就直接运行二进制文件</p><p>示例</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">C:\Users\Tom\Desktop\projections\rustLearn&gt;cargo run</span><br><span class="line">   Compiling rustLearn v0.1.0 (C:\Users\Tom\Desktop\projections\rustLearn)</span><br><span class="line">    Finished `dev` profile [unoptimized + debuginfo] target(s) <span class="keyword">in</span> 0.89s</span><br><span class="line">     Running `target\debug\rustLearn.exe`</span><br><span class="line">Hello, world!</span><br><span class="line">just <span class="keyword">do</span> it!</span><br></pre></td></tr></table></figure><p>如果编译过就没有Compiling这一行</p><p><strong>检查代码</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cargo check</span><br></pre></td></tr></table></figure><p>检查代码，确保能通过编译，但是不产生任何可执行文件。<strong>在编写代码的时候就没必要反复编译和运行，直接check就行</strong>，需要运行的时候再运行</p><p><strong>为发布而构建</strong></p><p>也就是发行release版本，编译时会进行优化，代码会运行的更快，但是编译时间更长。会在 target/release而不是 target/debug生成可执行文件</p><h2 id="项目的结构">项目的结构</h2><p>这里的项目结构是RustRover中的新建项目的结构</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">项目名</span><br><span class="line"> -src</span><br><span class="line"> --main.rs</span><br><span class="line"> -target</span><br><span class="line"> --debug</span><br><span class="line"> --.rustc_info.json</span><br><span class="line"> --CACHEDIR.TAG</span><br><span class="line"> -.gitignore</span><br><span class="line"> -Cargo.lock</span><br><span class="line"> -Cargo.toml</span><br></pre></td></tr></table></figure><p>源代码都应该在src目录下,顶层目录可以放置：README、许可信息、配置文件和其它与程序源码无关的文件</p><h3 id="Cargo-toml">Cargo.toml</h3><p>Tom’s Obvious,Minimal Language(toml) 格式,是cargo的配置格式</p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[package]</span></span><br><span class="line"><span class="attr">name</span> = <span class="string">&quot;rustLearn&quot;</span></span><br><span class="line"><span class="attr">version</span> = <span class="string">&quot;0.1.0&quot;</span></span><br><span class="line"><span class="attr">edition</span> = <span class="string">&quot;2024&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[dependencies]</span></span><br></pre></td></tr></table></figure><p>其中，[pacakge]，是一个区域标题，表示下方内容是用来配置包(package)的，name表示项目名，version为版本，edition为rust版本，{dependencies}为依赖，在rust中代码的包成为<strong>crate</strong>.</p><h3 id="Cargo-lock">Cargo.lock</h3><p>第一次运行cargo build 会在顶层目录生成cargo.lock文件该文件负责追踪项目依赖的精确版本，不需要手动修改该文件</p><h1>进入rust编程世界</h1><h2 id="数据类型、函数、注释">数据类型、函数、注释</h2><h2 id="控制流">控制流</h2><h1>参考资料</h1><ol><li>《The Rust Programming Language》v1</li><li><a href="https://www.bilibili.com/video/BV1hp4y1k7SV/?share_source=copy_web&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">Rust编程语言入门教程（Rust语言/Rust权威指南配套）【已完结】</a></li></ol>]]></content>
    
    
    <summary type="html">因参加2026春夏季开源操作系统训练营需要使用rust，遂开始学习使用Rust语言，旨在为后续任务开展打下基础</summary>
    
    
    
    <category term="rust" scheme="https://lloydkai.cn/categories/rust/"/>
    
    
    <category term="rust" scheme="https://lloydkai.cn/tags/rust/"/>
    
  </entry>
  
  <entry>
    <title>建筑、机械工程以及计算机专业劝退报告</title>
    <link href="https://lloydkai.cn/posts/quit-profession/"/>
    <id>https://lloydkai.cn/posts/quit-profession/</id>
    <published>2026-04-03T08:56:10.000Z</published>
    <updated>2026-04-23T01:43:39.943Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/22/kRytd2FQg3VH9NG.jpg" alt></p><h1>写在前面的话</h1><p>建筑行业我是在大一的时候接触的，所以我对其的了解仅限于浅层次；机械工程我学习了三年，并且家里和亲戚都有相关的技术背景，我本人也多次去相关的工厂实习看访过，这部分我会多写一点；计算机是我目前学习的专业，我会从劝退和劝入的角度分别讲解。</p><h1>建筑劝退</h1><p>就中国国内的建筑专业来分的话，一般主要有以下二级专业，分别是建筑学、城乡规划和风景园林，由于我本人在专业分流之前就已经转走了，所以我只从这三个专业的共同点来分析。</p><p>首先我先提一点，主要是针对<strong>先天性因素的</strong>，<strong>如果你是色弱或者是色盲，那么和绘画相关的专业你不能选，包括建筑专业</strong>，这个东西一般需要你事先在选专业之前充分了解的，一般会在高考之前会有一个体检，如果体检出有相关的遗传性因素，那么在选专业的时候就要排除，基因的缺陷会让你在从事本专业的时候处于劣势，无关努力，但也确实令人心酸，能做的就是及时止损，我就是这样。</p><p>所有想要选择建筑专业的学生，我个人认为必须要回答以下三个问题，如果这三个问题不能肯定地回答，那么就目前时代的发展背景而言，我强烈不推荐选择。</p><p><strong>第一，你有相当的美术基础吗？</strong></p><p>这里的美术基础，指的是你至少了解和学习过50小时以上的素描(无论是结构素描还是完整的素描)，如果你参加过美术艺考，那种水平基本上就是建筑专业的入门门槛。</p><p>以下我画的这个图就是结构素描还有完整素描的图(有点烂别介意，大概是这个样子)，如果你的绘画水平和我难分伯仲的话，我还是建议你算了吧😄。</p><p><img src="https://files.seeusercontent.com/2026/04/05/nFj1/190db0d.jpg" alt="结构素描图.jpg"></p><p><img src="https://files.seeusercontent.com/2026/04/05/1huP/dfa6d19.jpg" alt="素描图.jpg"></p><p>因为在20年代之前，如果你报考的是建筑专业，或者你要转行到建筑专业，在入学之前是要进行考试的(或者是个人成果集)，考试的内容一般就是结构素描，如果不通过的话就会把你调剂到其他专业。但是时过境迁，建筑行业做梦都想不到中国的房价下降得如此之快，建筑专业一下子从以前的香饽饽变成了“路边一条”，基本上除了“建筑老八校”以外，不再对学生的美术基础作出要求，你以为是对学生好，实际上是坑害那些没学过美术的学生，<strong>建筑就是披着工科皮的艺术专业，建筑就是披着工科皮的艺术专业，建筑就是披着工科皮的艺术专业</strong>！这句话我要反复强调，在国外建筑学是给那些从艺术学院出来人学的，国内也是这样，你在大一的时候上的最多的课就是设计课，高等数学是不修的，力学是阉割版本的。不学高等数学，不搞实验的，天天画图的你说它是工科，鬼都不信。</p><p><strong>第二，你热爱建筑绘画吗？</strong></p><p>如果你不能肯定的回答说“热爱”那么就是讨厌，而且<strong>注意我的前缀词，必须是“建筑”或者”城市规划图“或者“风景”</strong>,这三个分别对应上面三个专业,喜欢画人物、漫画的不行，这两者走的不是一个绘画的路子。建筑绘画讲究的是符合规律和规则，空间感和宏伟，人物绘画偏向的是微观，你只要画过建筑和人物，你就会清楚的知道这两个的不同。</p><p>以下我画的这个图就是建筑的图</p><p><img src="https://files.seeusercontent.com/2026/04/05/7ylW/cf8ffe8.jpg" alt="钢笔画.jpg"></p><p>这个图是钢笔画，如果你真的学建筑，后面还会学习油画、水彩、版印等，在入学的那一天，老师就会要求你们每周都要画3张A4的钢笔画或者是结构素描等，学了这门专业，你的余生都要与画笔为伴，<strong>如果没有热爱的话，真的很难支撑下去</strong>。</p><p><strong>第三，你的家庭经济基础好吗？</strong></p><p>这里的家庭经济基础，指的是家里能支撑你的学费，能够支持你读硕读博，能够每年支持大概2到3次左右的外出实习费用(一般是4000左右)，能够负担的起报绘画班、绘画材料的费用。</p><p>首先我要强调的是，相比隐形开支，学费显得一无是处。你每一个学期至少需要参加一个外出实习，一般就是到某一个旅游景点或者是知名建筑、风景区那边写生，问题就是，学校是不会负担你的门票费和住宿费的，而偏偏就是这些风景区的门票费、住宿和交通费用最贵。当你要开始写生的时候，你会发现要买的东西真是多——铅笔钢笔圆珠笔、专门的素描纸、画线笔、T字尺、支架、摄影机、颜料、建模板材、502胶水、美工刀、数位板等等，这些开销每一次花费大概几百左右，但是这样的开销次数多，可能几周就有一次。如果你以后要读研，会发现有一个专门的考试科目叫做快图，要求你在6小时之内画满A1的图纸，如果你不报班，不经过长期艰苦的努力训练，是不可能在6小时以内画完的。</p><p>最后我要强调的问题是，建筑专业的<strong>艺术本质</strong>。它的思维方式不是理工科思维，也不是文科思维，而是艺术生思维。<strong>完美按照黄金分割比的图纸不一定好看，但是好看的图纸一定是由那些有天赋的人画出来的</strong>，你懂我意思吗？艺术的本质是<strong>天赋</strong>，是只需要画几笔就知道灰与白应该怎样表现，看几次就知道光应该从哪里入射，哪里画得暗，在哪里画几笔会凸显立体感，在画画之前就在脑海中构思完整个图的全貌…  这些都会让理工科的人感到不知所措，<strong>艺术是没有标准答案的</strong>，很多时候就是一种感性的理解和表达。如果你去看建筑专业的作业答辩，你会发现整个过程没有对理论的讨论，都是“我觉得这样怎么怎么好看”，“表现出了建筑的宏伟与壮观“，“突出了人文风貌和风土气息”，换句话说，建筑适合充满想象力、有绘画能力、对美有独特的理解和思考，最好带有一点口才的人去学，发现了没？这些完美契合女生的气质，这也是建筑专业女生多的原因，而长期学习理工科的学生我不是特别建议，因为你们的思维早已是1+1=2的，无论怎么样你都不能接受1+1=3甚至1+1还可以等于4。</p><h1>机械劝退</h1><p>机械在当下这个时间段可以说是T1专业了，可以和计算机、电气等专业结合，工作是不用愁的，只是你愿不愿意去做。上至高级技工，下至钢板搬运工，在哪里都可以充分就业。不过在选择这个专业之前，我简要的介绍你要学习的东西、工作的环境和未来的趋势。</p><p>目前中国的机械工程是一级学科，一级学科下面还有许多的二级学科，比如机械设计制造及其自动化、车辆工程、智能制造、材料工程、汽车服务、机器人工程等。二级学科有很多，不同的学校有不同侧重，比如南方的机械一般侧重轻工业、北方的侧重重工业，国防相关的侧重军工、北上广深侧重机器人等。机械能做的事情很多，要学的东西也很多，所以需要有所侧重。</p><p>通常来说，机械工程(这里指的是传统的机械，也就是不带“电”)在大一的时候要学<strong>机械制图</strong>，这个是重中之重，无论你是干低端的加工制造，还是高端的数控机床、机器人，你都需要认真学习，具体长什么样你可以在网上看，我要提醒的是这门课程对空间想象的能力要求高，如果你的几何不太好，对以后的学习就业可能会造成一定影响，还有就是<strong>CAD</strong>，也就是用计算机画图，也是重点必须熟练掌握。</p><p>而在大二的时候，你学习的侧重点就是各种力学——<strong>理论力学、材料力学、流体力学</strong>，还有两门专业课，如果你选择的是机械设计制造及其自动化，你的专业课就是机械设计和机械制造；如果是车辆工程，就是汽车理论。无论是哪一门专业，我都要强调的是，<strong>你的力学必须好</strong>，数学会根据公式算就行。<strong>如果你高考物理都不及格，或者是力学怎么学都学不会，我不建议你学机械工程</strong>。在你设计机械产品或者制造的时候，用的最多的就是力学分析，公式计算。</p><p>而其他要学的科目根据不同的二级学科有所不同，如果是偏自动化的，会学模电数电、控制工程、复变函数、单片机等；如果是偏电气的，那么就会学电路、电磁场等；如果是偏制造和加工的就会学数控机床、精密仪器检测等。其实这个就是机械的发展趋势——<strong>复合专业</strong>。网上经常会说，<strong>机械不带电，饿死一大片</strong>，在找工作的时候，如果是单纯的设计岗位或者是加工岗，一般开到6k到8k就算比较高的了，而如果你会一些电气工程的知识，会自动化、数控编程的话，工资就可以上w。也就是说，<strong>你在选择机械工程的同时，也需要选好其下的二级学科</strong>，每一个学科学到的知识，都会转化为未来求职的工作要求。有的学校会在高考选专业的时候就确定，有的学校是在大一之后再进行专业分流，这方面你要多多注意，往往越好的机械二级学科越难越不好考。</p><p>那么你工作的时候用的最多的是什么软件呢？一般来说机械工程的都要学习Solidworks与AutoCAD，前者在设计加工、绘图等都用的上，后者就是机械制图用的，车辆工程的要学rhnio和UG，嵌入式方向要学keil，机器人要学ROS等。我推荐你在确定你是否选择机械专业之前先把这两个软件下了并且在网上找视频学习（跟着做就行，不需要先学理论再画图），如果你不讨厌甚至有一点喜欢，那么就可以选；<strong>如果你感到无感甚至对枯燥的设计和绘图厌烦，那么就不要选</strong>。</p><p>至于其他的科目，我的建议是，你根据你以后的求职方向选择性学习，因为学校里教的很多东西都过时了，不过机械还算是一个古老的学科，虽然落后了一点，但是核心的知识还在，只是你要根据时代的变化去补充你欠缺的能力和知识，以便在未来求职夺得先机。</p><p>那么机械专业的工作环境是什么样子的呢？请自己在网上搜索<strong>金工实习</strong>的视频，那个地方大概率就是你以后工作的地方，设计岗会稍微好一点，但也只是好一点，你还是要随时到这个地方看你设计出来的产品的。这里我要强调的是，<strong>工作环境的污染程度和危险程度超乎你的想象</strong>。你知道有一种东西叫做碳纤维吗？如果你长期生活在碳纤维敞开的环境下，你的呼吸道会损伤，最严重的情况下就是呼吸道灼伤，导致以后呼吸的时候食道都会痛(真实案例)；工厂里面还有一个隐形的杀手是加工的噪音——机床刀具切割声、金属碰撞声、焊工电焊的声音等，预估环境分贝在80分贝左右，长期待下来你的听力一定会受损。你可能会说难道工厂不会发隔音耳罩吗？难道不会像精密工厂那样专门设置一个清洗间和防尘服供员工穿吗？孩子，这是制造业，不是内存厂，制造业的利润率本来就低，为了多挣点钱，只好委屈一下员工，耳罩是没有的，厂房是不打扫的，经常是24小时轮班制的，老板是没文化土财主的，骂声是难听的，宿舍是堪比陋室铭的，工厂饭堂是堪比潲水的。除非真心喜欢制造和习惯机油味的、迫于生计和技术水平不得不做的，我想不到还有什么样的人会去这样的地方。自从我第一次进入到这个地方，我就在想，如果要选择一种死法，我宁愿选择在电脑前猝死，也不愿死在满是灰尘和油污的厂房中。<strong>环境好的地方不是没有，仅限于北上广深</strong>，我建议选择这一行的人都尽量往这些地方跑，为了你的身体安全和健康，也为自己的前途命运着想，在二三线城市制造业是真的把员工当耗材的！</p><p>最后我给你们解答一些常见的疑惑。</p><p><strong>机械专业，越老越吃香</strong>：这其实只说了半截话，另一截是“<strong>前提是你真的喜欢</strong>”，不喜欢怎么可能支持你从事这个专业到老。</p><p><strong>机械专业，工作不愁</strong>：模糊的表述，工作确实不愁，3k4k的在小县城多的是，一般就是搬运钢材、齿轮等，这种重体力活等你赶到三四十岁左右的时候你大概率就要被辞退了，你可能会说难道工厂还没有实现用机器人搬运吗？说句比较地狱的话，<strong>因为人工成本比机器人低，所以现在很多某些地方还在用人工搬运</strong>。</p><p>其实我个人来说，最大的无奈就是机械的制造业本质——在工业克苏鲁的中国，机械在其中起到了中流砥柱的作用，也付出了难以想象的代价，请问中国制造是如何畅销全世界的，无非就是物美价廉，物美就是靠技术的提升，价廉就是靠压榨和大量生产，制造业的本质注定了整个行业的利润率低，能达到10%就算很好的了，很多时候都是赚的辛苦钱，老板、股东、CEO等要分走大部分，留给技工、工人的少之又少。如果你看过《大国工匠》系列记录片，你会发现，哪怕是这些在技术上精益求精甚至巅峰造极的人，哪怕已经攻克了一个又一个的难关，他们的待遇完全和付出不相匹配。如果把同样的努力和天赋发挥到金融、计算机等领域，他们的回报会是制造业的好几十倍。在你选择之前，你问问自己，你能接受这样的结果吗?你是一个把技术放在金钱、荣誉和地位之前的人吗？你是一个哪怕穷困潦倒依然热爱制作的那个少年吗？如果不是的话，还是选择其他相对轻松回报高点的专业吧。</p><h1>计算机劝退</h1><p>以下图片是节选自网上评论的，讲得基本到位。</p><p><img src="https://files.seeusercontent.com/2026/04/06/1oCl/ed52185.jpg" alt="计算机专业劝退.jpg"></p><p>如果你还想要确认你是否喜欢计算机。我给你布置一个任务。放心，这个任务对于哪怕没有学过计算机的人也能完成，只是看你有没有这方面的兴趣和特质。</p><p>任务：请编程实现《Python编程：从入门到实践》这本书后面的外星人入侵的项目，并且将其推送到github上自己的仓库中，同时写一个README.md文件分别用中文和英文简要介绍这个项目。</p><p>要求：你可以选择任意的编程语言实现，甚至可以选择其他的项目，只要复杂程度和这个项目差不多就行(用Python实现大概600行代码，对于没学过计算机的人来说算比较多的了)。你可以选择购买这本书，或者以其他的方式获取。要自己一行行编程(不准使用AI)，需要的环境自己配置，出了Bug自己修，必须能完整实现书中项目的功能。md是markdown语法，自己学。github自己注册，想办法登录和推送(必须是github，gitee不算），使用什么样的工具你自己找。</p><p>好了，我等你一会儿，如果真是零基础要完成以上项目估计要至少三天到一周。</p><p>做完了吗？没做完？不想做？好的你可以不用选这个专业了，<strong>这就是计算机专业以后要做的事情，并且只会比这个难</strong>。</p><p>做完了？不错，你有学习计算机的重要的品质——<strong>独立解决问题的能力，善于搜索查找资料的能力，快速学习的能力，细心与坚持，有一定的英语水平，再加上对体制化的反感和对规则的突破</strong>。但是我还是要问你一些问题，你在心里回答就行，回答完了不用我多说你就知道你要不要选计算机了。</p><p>你在做这个项目的时候感受到快乐了吗？是过程快乐还是结果快乐？</p><p>你愿意一辈子活到老学到老吗？能够时刻保持对新知识和技术的好奇吗？</p><p>你愿意一辈子和代码朝夕相处吗？哪怕35岁失业，身体被摧残，日复一日在电脑前坐着吗？</p><p>好了，我的问题问完了，相信你有答案了。<strong>计算机确实是好专业，但仅限于热爱的人</strong>。</p>]]></content>
    
    
    <summary type="html">为在高考选择某一专业和转行的人提供这三种专业的劝退信息，旨在警示自己和后人。</summary>
    
    
    
    <category term="专业" scheme="https://lloydkai.cn/categories/%E4%B8%93%E4%B8%9A/"/>
    
    
    <category term="专业选择" scheme="https://lloydkai.cn/tags/%E4%B8%93%E4%B8%9A%E9%80%89%E6%8B%A9/"/>
    
  </entry>
  
  <entry>
    <title>2026春夏季开源操作系统训练营学习</title>
    <link href="https://lloydkai.cn/posts/opencamp-os/"/>
    <id>https://lloydkai.cn/posts/opencamp-os/</id>
    <published>2026-03-29T22:47:12.000Z</published>
    <updated>2026-04-23T01:43:14.247Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/oJZ7zDkcdrv9q5I.png" alt></p><h1>官方网站</h1><p><a href="https://opencamp.cn/os2edu/camp/2026spring">官方网站链接</a>，有任何的疑问和咨询都可以在官网上查到，自行学习</p><h1>导学阶段</h1><h2 id="操作系统基础知识">操作系统基础知识</h2><blockquote><p>这部分我在学408的时候就基本掌握的大部分的知识，这里看一下官方的教学视频，回忆一下知识点即可，后续还是要在实战中学习。</p></blockquote><h2 id="rust学习">rust学习</h2><p>这部分的笔记我转移到以下这个博客中，有需要的时候就看。</p><ol class="series-items"><li><a href="/posts/rust-series-one/" title="Rust系列(一)Rust语言基础">Rust系列(一)Rust语言基础</a></li></ol><h2 id="Git、Linux等工具使用">Git、Linux等工具使用</h2><p>这部分自己查找资料即可，学习git推荐用<a href="https://learngitbranching.js.org/?locale=zh_CN%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9B%B4%E8%A7%82%E7%9C%8B%E5%88%B0%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%88%86%E6%94%AF%E5%92%8C%E7%BB%93%E6%9E%84%E3%80%82">https://learngitbranching.js.org/?locale=zh_CN，可以直观看到项目的分支和结构。</a></p>]]></content>
    
    
    <summary type="html">由清华大学的陈渝老师和向勇老师于 2020 年发起，旨在通过使用 Rust 语言编写操作系统的实践，培养全国高校学生的操作系统开发技能。训练营全程免费，指导学员参与开源项目实战，探索设计与构建新一代安全高性能操作系统。本博客记录个人学习的过程，旨在为参与开源项目和工程实践积累经验</summary>
    
    
    
    <category term="OS" scheme="https://lloydkai.cn/categories/OS/"/>
    
    
    <category term="开源社区" scheme="https://lloydkai.cn/tags/%E5%BC%80%E6%BA%90%E7%A4%BE%E5%8C%BA/"/>
    
    <category term="OS" scheme="https://lloydkai.cn/tags/OS/"/>
    
    <category term="rust" scheme="https://lloydkai.cn/tags/rust/"/>
    
  </entry>
  
  <entry>
    <title>电子产品购买使用经验总结</title>
    <link href="https://lloydkai.cn/posts/electronic-product/"/>
    <id>https://lloydkai.cn/posts/electronic-product/</id>
    <published>2026-03-19T03:54:12.000Z</published>
    <updated>2026-04-23T01:43:27.897Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/XbDpP8Rt5ITuU9H.jpg" alt></p><blockquote><p>以后统一展现图片尺寸为1220*728 也就是16:10</p></blockquote><h1>磁盘类</h1><p>目前比较推荐的是我在淘宝上收藏的机械硬盘，西部数据My passport随行版，以及忆捷的双盘位机械硬盘。</p><p>尤其注意<strong>机械硬盘和U盘买回来记得拍开箱视频和做扩容检测</strong>，特别是非官方店铺，之前我就买过一个翻新盘。</p><p>如果是存储容量比较大的机械硬盘，大概测个1TB就差不多了，直接随机取样，如果坏块过多的话就直接退了。</p><p>目前<strong>避坑的就是梵想的PS2000</strong>，以后不要买这个品牌的了，在使用一年左右就会掉盘，而且掉速特别严重，非常搞人心态。</p><p>不过价格就这个数，如果你能忍受只使用1年也还可以。</p><p><img src="https://files.seeusercontent.com/2026/03/19/6Tkt/tip_PS2000.jpg" alt="tip_梵想PS2000.jpg"></p><p>西部数据还可以，就是它需要密码解锁(后面可以通过安装它的软件实现开机就解锁)，如果想要即插即用还是看其他的品牌。</p><p><strong>西部数据my passport随行版</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/c5Hm/tip_WD_SSD.jpg" alt="tip_WD_SSD.jpg"></p><p>另外提一点的是，这个是我在2024年买的，所以价格比较低，目前由于内存短缺，1T的价格已经达到了1200元，如果不着急的话建议多等等，<strong>在600-700左右就是正常价格</strong>。</p><p><strong>忆捷机械硬盘</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/O4fo/tip_.jpg" alt="tip_忆捷机械硬盘.jpg"></p><p>配合到补贴大概就是200左右1T，还可以，经过测试之后<strong>读写速都是65MB/s</strong>。</p><p>说明书：扫以下连接即可查看，一般两个盘都是默认NTFS的格式，有需要就自行格式化。</p><p><img src="https://files.seeusercontent.com/2026/03/19/dNy2/tip_.png" alt="tip_忆捷机械硬盘说明书.png"></p><p>我个人比较推荐买这种双盘位的，<strong>一个盘给macmini用做时间机器盘，另一个就用来存数据</strong>。或者你会分盘直接买一个1T的自己分也行。</p><h1>移动WiFi</h1><p><strong>唯一可靠的是官方的的移动WiFi</strong>，其他的全都不要信。</p><p><strong>避雷</strong>：<strong>速登随身WiFi</strong>，完全就是骗人的货，说是一个月50G，实际测速下来还不如流量。</p><h1>主机电脑类</h1><h2 id="MAC-mini">MAC mini</h2><p>一般来说这种主机的选择优先级是内存&gt;主存，结论就是<strong>能16GB就不要8GB</strong>，如果你不是那种做视频剪辑或者是平面设计那种需要大量素材的，内存256G其实差不多了，mac实际上能占用内存空间的软件并不多。</p><p>但要注意的是，内存256G实际上很容易降低硬盘健康度，所以最好不要频繁写入数据。</p><p><strong>MACminiM1</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/5Zhv/tip_macminiM1.jpg" alt="tip_macminiM1.jpg"></p><p>目前由于<strong>龙虾潮和内存短缺</strong>，要买Macmini M1 16G+256G二手价格已经到了3000元，还好我成功抄底😼</p><h2 id="iMac">iMac</h2><p>非常适合家用办公。如果是一个intel系列的话咸鱼只需要2000左右，有的还有MACOS和Windows10双系统</p><p>但是m1的就要5000起步了。</p><p>如果给家里人用，2000差不多了，丐版足够家里人用了。</p><p>如果自己用，感觉还是比不上MacBook pro或者是MAC mini +配件的组合。</p><h1>平板</h1><p>对我而言<strong>平板是一个尴尬的产品</strong>，主要是用于看视频的，或者是临时过渡的外壳。</p><p>我更迫切需要的是扩展屏，拿买平板的钱可以买很多不错的扩展屏。</p><p>所以，除非有非常迫切的需要，建议不要买平板，要买也只能是中间价格(不能超过三千，否则还不如买一个二手MacBook)。</p><p>触控笔、平板的键盘不要买了，智商税，<strong>不要给自己创造需求，只有当你想了很久确实需要并且非它不可的时候再买才能物超所值</strong>。</p><p>后面我就把我的联想的平板当作一个256GB的硬盘了。</p><p><strong>联想小新pad</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/D6wn/tip_Pad.jpg" alt="tip_联想小新Pad.jpg"></p><h1>显示屏和扩展屏</h1><p>如果是放在寝室里的，一般的1920X1080 就够用了，高刷就看个人需求了</p><p>如果你买了苹果电脑，那么我<strong>极其推荐你买一个4k的显示器</strong>，如果你用4k以下的显示器连接MacBook的话是不会开启Hidpi的，需要自己通过命令行设置。</p><p><strong>4k显示屏</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/c7sJ/tip_4K60Hz.jpg" alt="tip_4K60Hz显示器.jpg"></p><p>反正我穷鬼一个，能用就行😂</p><p>至于扩展屏，如果你确实感觉屏幕不够用，可以买一个，不过注意买支架什么的。</p><p>有些扩展屏可以支持触摸，这个其实意义不大，除非你就是买来连接手机用的，购买之前注意看设备的支持清单。</p><p><strong>扩展屏</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/qJ6d/tip_.jpg" alt="tip_便携屏.jpg"></p><p><strong>支架</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/k4Zd/tip_.jpg" alt="tip_便携屏支架.jpg"></p><h1>手机</h1><p>我对手机的定位是——必须要用的产品，但不太需要用高端产品。</p><p>也就是说，以后我买手机优先考虑<strong>小米(主要是为谷歌框架)</strong>，价位大概3000-4000.然后就是其他产品，不考虑华为，里面广告巨多。</p><p>折叠屏是吹出来的泡沫，不考虑。</p><p>如果可以root更好，但是基本上没有几个手机可以root了。</p><p>苹果手机等以后有钱了可以买一个，但也只限于买一个，主要是用于苹果生态。</p><h1>键盘</h1><p>目前我手里狼蛛一个、双系统键盘一个，mac平替妙控键盘一个、家里108键一个，基本上不需要再买键盘了，完全能满足需求。</p><h2 id="平板键盘">平板键盘</h2><p>如图下方键盘，上方的是多系统适配键盘，下方的是平板键盘。</p><p><img src="https://files.seeusercontent.com/2026/03/19/yr4E/tip_.jpg" alt="tip_平板键盘.jpg"></p><p>就我实际使用经验来看，<strong>对我而言是智商税</strong>。因为<strong>平板在我心目中的定位过于尴尬，便携不如手机，专业不如电脑</strong>，很多人说平板可以用来画画、手写笔记，但就我个人而言，用电脑画图、写md文件比手写又快又有效，完全用不着用平板，之前我就是被这种消费陷阱骗了，实际上根本用不到几回。如果你买的是类似小新pad这种比一般的平板小的，那么对应的键盘就是上面的，<strong>这种很难用</strong>，比一般笔记本电脑的还要小，在点击enter、delete这样的键很容易误触，大大降低了打字的体验。</p><p>哪怕一般的平板大概24mm左右长，而对应的键盘大概只有22mm，比常规的mac键盘要小很多，尤其是你看右上角的回车、删除键，右下角的上下键，非常小，基本很难点到，所以<strong>我强烈不推荐用这种键盘</strong>。</p><h2 id="多系统适配键盘">多系统适配键盘</h2><p>如图上方键盘所示</p><p>问题同平板键盘一样，还有一个突出的问题是，这种键盘既不像windows又不像mac的，就给人的感觉十分尴尬。本来适应双系统的键盘就已经够了，还要再整一个第三种的键盘，属实匪夷所思。</p><p>这种适配的需求感觉也是营造出来的，<strong>你带什么电脑出去，就用什么样的键盘，不需要带一把瑞士军刀，样样精通就是样样稀松</strong>。</p><p>我目前还保留了一个键盘，以后不要再买这种键盘了。</p><h2 id="一般键盘">一般键盘</h2><p>先说结论，对于我这种计算机的来说，<strong>87键就够用了，最推荐的就是狼蛛</strong>。完全不需要98键甚至108键(区别就是右边会多出来一些数字键和home、end等键)</p><p>对于右边的那21个键我可以说4年使用的次数屈指可数。</p><p><strong>常见的108键键盘</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/q2wW/tip_.jpg" alt="tip_机械键盘.jpg"></p><p><strong>狼蛛键盘</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/b0kG/tip_F87Pro.jpg" alt="tip_狼蛛F87Pro.jpg"></p><p><strong>小键盘</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/oiY8/tip_35.jpg" alt="tip_35小键盘.jpg"></p><p>小键盘有一种情况是可以买的，如果你是类似搞机械的使用软件设置快捷键在右侧数字键上(比如SW)或者是会计之类的需要频繁输入数字的，那就可以买，如果你没听说过，那就不用买。</p><h2 id="妙控键盘及其平替">妙控键盘及其平替</h2><p>先说结论，国产的妙控键盘可以使用，大概能够满足90%的需求，不过有以下缺点，如果这些缺点确切影响到了你的使用，还是老老实实买官方的妙控键盘——建议不要买二手的，因为涉及到ID绑定的问题</p><p><strong>平替秒空鼠标和键盘</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/ze4N/tip_.jpg" alt="tip_高仿妙控鼠标和键盘.jpg"></p><p><strong>缺点如下</strong></p><ol><li>最左下角的fn键和最右上角的键(要么是触控ID键要么是菜单键)基本无法使用，fn只在和F功能键一起按的时候才能用。</li><li><strong>必须要使用2.4G连接</strong>，如果你打字速度不快的话(一分钟60字以下)影响不大。如果对速度敏感就不要买平替，打字快了会出现各种问题,比如丢失按键或者是重复输入。</li><li>有些平替的可以直接用F11mac的功能键，有些要配合fn才能使用，而且还无法设置，不知道什么原因</li><li>有部分厂家生产的键为了同时适配Windows和MAC，<strong>修改了部分苹果原本的键盘布局</strong></li><li>(主要是针对文字写作者的)如果你之前习惯了用狼蛛这种比较高的键盘，用mac这种很低的键盘会很不适应。</li></ol><p><strong>个人经验</strong></p><p>总结：如果不是为了macmini，或者是需要mac电脑外接显示器的情况，我个人还是推荐，<strong>如果有打字、coding的需求，可以买一个三模的机械键盘有线连接mac，这样就无需适应苹果的键盘</strong>。</p><p>如果你买的是官方的键盘和妙控板，强烈推荐买一个妙控键盘增高底座（就是那种3D打印的那种，官方原版可以直接将其嵌入进去）</p><p>如果是平替也可以买，用双面胶就可以解决不匹配的问题（直接粘在上面，如图所示）</p><p><img src="https://files.seeusercontent.com/2026/03/19/e9Yh/tip_.jpg" alt="tip_增高后的键盘.jpg"></p><p>这样就可以增高，模拟机械键盘，对手腕比较好。</p><p>增高尺寸分别为：前侧1cm,后侧2.4cm</p><p>由于我这个是直接贴在上面的，所以如果是用原版苹果的键盘，这种键盘是直接嵌入到这个壳里面的，前侧增高0.7cm，后侧增高1.5cm</p><h1>鼠标</h1><p>目前我手里有两个鼠标，一个是英克斯的鼠标(无线充电款)，另一个是惠普的鼠标(无线电池版)，后者用于苹果</p><p>还有一个鼠标是握式鼠标，主要是用来<strong>减少腱鞘炎的，打游戏是别想了</strong>，但是需要适应。一般人就别买了。</p><p>还有一个鼠标是苹果平替，主要是配齐“全家桶”，反正也只要35,这个价钱要什么自行车。</p><p><strong>英菲克鼠标</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/8jGj/tip_.jpg" alt="tip_英菲克鼠标.jpg"></p><p><strong>立式(握式)鼠标</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/vq1V/tip_.jpg" alt="tip_立式鼠标.jpg"></p><p>苹果平替鼠标见前图tip_高仿妙控鼠标和键盘.jpg</p><p><strong>目前的建议是：</strong></p><ul><li>如果你想要一劳永逸，以后就不换鼠标，一年换一次电池，那么就建议<strong>买电池款式的</strong>。</li><li>如果你想要轻便的，建议买<strong>能显示电池状态的</strong>，方便及时充电。</li></ul><p>电池款的鼠标一般<strong>偏重</strong>，不太适合需要频繁移动的场景(就是打射击类型的游戏，还好我不打😄)</p><p>而对于苹果电脑而言，大部分情况下苹果用触控板就能够完成任务，鼠标只是用于精细化操作。</p><p><strong>苹果鼠标国内平替的缺点如下</strong></p><ol><li>大部分手势不能用</li><li>不管是官方的还是平替的，最大的问题感觉还是太矮了，不符合人体工学，对手腕的要求大</li></ol><p>对于苹果鼠标，我的建议是，当你需要使用的时候再将鼠标打开机，否则就只需要使用触控板就可以了。</p><p>目前我尝试使用了苹果鼠标的平替，我只能说不是特别好用，尤其是手指上下滚动，移动还好，但是涉及到滚动的基本上需要小心翼翼使用，所以以后就不买苹果的鼠标，对我而言太难用了。</p><h1>触控板</h1><p>就我实际操作而言，<strong>Windows系统不太适合用触控板</strong>，因为手势涉及到的核心功能是切换桌面和调度平台，而Windows做的很垃圾，苹果就非常适合。</p><p>如果没有足够的钱，买一个国产的200左右的触控板就能满足90%的功能了，<strong>缺点就是需要用有线连接才能用，以及没有两级触控</strong> .</p><p>以后有钱了可以去买一个官方的magic trackpad，正版大概600左右。</p><p><strong>平替触控板</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/5cyY/tip_.jpg" alt="tip_高仿妙控板.jpg"></p><h3 id="增高垫">增高垫</h3><p>因为我比较习惯用狼蛛的键盘，而原生的妙控键盘和触控板对我来说有点低，所以需要增高</p><p>注意网上增高的只支持苹果官方正版的，那些买高仿的就不要想了(就是我自己)</p><p><strong>秒控键盘底座</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/7Efy/tip_.jpg" alt="tip_妙控键盘增高垫.jpg"></p><p><strong>妙控板底座</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/Kob5/tip_.jpg" alt="tip_触控板增高垫.jpg"></p><p>对于妙控键盘，还有一种方法就是用这种，实测好用，<strong>建议买四个贴在四个角落上</strong></p><p><strong>支撑脚</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/L6nr/tip_.jpg" alt="tip_键盘支撑架.jpg"></p><h1>数位板</h1><p>目前我用的比较顺手的是<strong>高漫的</strong>，价位基本在200左右对一般的绘画者来说也差不多了。</p><p>有时候会考虑到买一个数位屏，但是很贵，除非有钱或者是确实已经达到了一定的绘画水平且能够在这方面投入足够的时间，再考虑购买。</p><p>我是因为要在PS上画图和在电脑上手写笔记才买的，如果你没有相应的需求，就不要随便买，画画可不是一天就能练成的。</p><p><strong>友基数位板</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/fs6R/tip_.jpg" alt="tip_友基数位板.jpg"></p><h1>耳机</h1><h2 id="无线蓝牙耳机">无线蓝牙耳机</h2><p>其实就是Buds系列，这个我比较推荐买，<strong>主要是降噪功能很好用</strong>，这样我就不用上课听讲了😄。</p><p>注意买的时候和手机配套，比如你是小米手机就买小米的buds</p><p><strong>小米buds</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/hv2H/tip_Buds.jpg" alt="tip_小米Buds.jpg"></p><h1>音响</h1><p>这个看个人需要了，如果经常喜欢听歌或者是看视频的，还是建议买一个好一点的，就那电脑的破喇叭是听不了什么好的声音的。</p><p>如果桌子比较小，可以买那种方形的、圆柱形的音响，效果一样可以。</p><p><img src="https://files.seeusercontent.com/2026/03/19/2vLs/tip_.jpg" alt="tip_音响.jpg"></p><h1>配件类</h1><h2 id="网线">网线</h2><p>目前来看推荐的是10Gbps或者以上的，就日常而言10Gbps的够用了</p><p><img src="https://files.seeusercontent.com/2026/03/19/3eRk/tip_.jpg" alt="tip_网线.jpg"></p><p>这个是10Gpbs的，如果追求的是极致的网速就向上买。</p><h3 id="MACmini连接网线教程">MACmini连接网线教程</h3><p>以下是学校连接网线的教程，家用宽带等同理，不过可能需要根据WiFi的位置买比较长的网线。</p><ol start="0"><li>根据实际情况买对应尺寸的网线，并且连接</li><li>点击设置-网络-…-添加服务</li></ol><p><img src="https://files.seeusercontent.com/2026/03/19/7mpK/tip_PPPoE_001.png" alt="tip_PPPoE_001.png"></p><ol start="2"><li>接口选择PPPoE,以太网选择以太网</li></ol><p><img src="https://files.seeusercontent.com/2026/03/19/8Jwp/tip_PPPoE_002.png" alt="tip_PPPoE_002.png"></p><ol start="3"><li>点击详细信息，然后在里面输入自己的账户名称和密码，比如学校的校园网一般账户名称是学号，密码是默认的，具体是什么还需要联系运行商，比如你是联通的就需要询问联通的运营商。</li></ol><p><img src="https://files.seeusercontent.com/2026/03/19/8Jwp/tip_PPPoE_002.png" alt="tip_PPPoE_002.png"></p><ol start="4"><li>注意学校里面的校园网一般不稳定，认证时间比较长，所以需要多次连接才能成功</li></ol><h2 id="转接头-充电头-适配器">转接头(充电头/适配器)</h2><p>血泪教训：<strong>在买转接头和线的时候一定要官方原配，不要东批西凑，也一定要看支持的功率和品牌类型</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/5bIs/tip__5V2A.jpg" alt="tip_转接头_5V2A.jpg"></p><p>这种转接头基本上只能充那些<strong>小功率电子设备</strong>，家里有一两个就差不多了。</p><h2 id="扩展坞">扩展坞</h2><p>目前USB已经更新到4版本了，对于苹果电脑就买<strong>雷电系列</strong>，其他的电脑至少是3.0(因为以前设备的接口不支持),不要买2.0的了。</p><p>就USB协议官方说，<strong>USB4其实就是更加灵活的雷电3</strong>，可以预见以后USB3.0系列会慢慢淘汰，以后买相关的电子设备也要开始优先考虑是否支持USB4和是否拥有相关的接口。</p><p>如果想要了解详细的内容请参考以下链接</p><ol><li><a href="https://www.usbzh.com/article/detail-1382.html">USB中文网</a></li><li><a href="https://www.usb.org/usb4">USB-IF </a> 这个是官方网站</li></ol><p><strong>联想扩展坞</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/j8tK/tip_.jpg" alt="tip_联想扩展坞.jpg"></p><p>注意你如果是买的这种立式的扩展坞，一是建议买线稍微长一点(0.5m以上),二是不太建议接固态硬盘、机械硬盘等大型外接设备，接线和摆放会比较难受。</p><p><strong>立式扩展坞</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/m3Du/tip_.jpg" alt="tip_惠普立式扩展坞.jpg"></p><h2 id="数据线">数据线</h2><p>如果想要发挥雷电线的优势，必须是，<strong>电脑支持雷电接口(<strong>目前基本上都是苹果)，<strong>数据线必须是雷电线</strong>，如果要接硬盘，必须要通过</strong>支持雷电的硬盘盒</strong>，在硬盘盒插入硬盘(其速度必须和雷电的速度差不多)，才可以最大限度发挥速度。</p><p>注意一般的SSD撑死就支持1000MB/s,根本达不到雷电3的门槛，而且一般支持的都是USB3.2，传统的SSD速度的限制无法达到雷电4的速度</p><p>目前国内有制作雷电5数据线的厂商，我也买了一个，但是还没有测试，这里先挖一个坑，等后面测试之后我再补上😏。</p><h3 id="雷电数据线">雷电数据线</h3><p>如下图是我买的国产的雷电5的数据线(不知道是真是假)，苹果官方的要几百甚至上千</p><p><img src="https://files.seeusercontent.com/2026/04/02/4qwB/tip_5.jpg" alt="tip_雷电5数据线.jpg"></p><p>目前还没有测试，但是个人实践表明，用来在电脑和手机之间传输数据特别好用。</p><p>同时也提醒，一般<strong>安卓手机支持的是exfat或者是fat32文件系统，不支持ntfs</strong>,如果想要直接将Windows电脑上的数据直接传输到安卓上，要么通过localsend这种两端的应用传输，要么通过数据线，或者通过应用让手机“支持”ntfs。目前我推荐用数据线的方式，应用的方法对流量的消耗比较大。</p><h2 id="触控笔">触控笔</h2><p>我目前买了一支。</p><p><strong>触控笔</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/Mnz8/tip_.jpg" alt="tip_触控笔.jpg"></p><p>建议<strong>如果不是艺术专业或者不是重度手写笔记、绘画爱好者，这东西不要买</strong>，如果买的太差你会觉得还不如手写，太贵的你如果用不上几回就亏了。你看网上吹这种东西的不是画画的就是喜欢做手写笔记的，它的问题和平板键盘是差不多的，当且仅当没有这个会显著影响学习才考虑购买，不过只要稍微思索一下就直接打消想法了。</p><h2 id="手环和智能手环">手环和智能手环</h2><p><img src="https://files.seeusercontent.com/2026/03/19/7fYf/tip_007.jpg" alt="tip_007.jpg"></p><p>一种是类似我这种的，最大的特点是屏幕是LED灯，<strong>这种手环基本就是图一乐</strong>。检测公里数和运动步数都是靠震动实现的，准确性差。不过比较好的一点就是无声闹钟确实可以，就相当于有人在摇你，可以一定程度上替代闹钟。至于睡眠检测就别想了，这么一点怎么可能有好的检测效果，人家苹果都要在专门的硬件上开发watchos，你这单片机直接打发了。</p><p>价格：最多30好吧，我的就是这样</p><p>另一种就是比较正规的手环，各家的都有，特点就是自带屏幕和一定程度的OS系统。</p><p>还是那句话，<strong>不要创造需求，确实需要的时候才买</strong>。</p><h2 id="读卡器">读卡器</h2><p>这个是用来读SD内存和摄影机TF卡这种内存的，有需要的才买，目前我对这种产品的读取速度不敏感，如果有速度要求就需要用别的东西</p><p><strong>读卡器</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/Vy8f/tip_.jpg" alt="tip_读卡器.jpg"></p><h2 id="充电宝">充电宝</h2><p>就我个人购买情况来看，如果你买的是那种高功率的(比如120W),往往在收到货的时候建议你要完成几次充放电再用，否则会有<strong>虚电现象</strong>。</p><p>实际应用来看，建议还是买40W50000mA以上容量的充电宝，<strong>如果要带上飞机一定要有3C认证</strong>。</p><p>50000mA基本上能充一般的手机从20到100大概2次半。</p><p><strong>充电宝</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/yF6j/tip_.jpg" alt="tip_充电宝.jpg"></p><h2 id="理线器">理线器</h2><p>多的也不说了，你只要觉得数据线太多太杂的时候，就应该买了。</p><p><strong>理线器</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/n5Tp/tip_.jpg" alt="tip_理线器.jpg"></p><h2 id="数据线收纳包">数据线收纳包</h2><p>如图所示，建议买大一点的，你永远不知道一根线有多么占空间</p><p><strong>数据线收纳包</strong></p><p><img src="https://files.seeusercontent.com/2026/03/19/P3ql/tip_.jpg" alt="tip_数据线收纳包.jpg"></p>]]></content>
    
    
    <summary type="html">总结购买电子产品的经验和使用技巧，为后续设备的挑选提供宝贵的参考</summary>
    
    
    
    <category term="CS" scheme="https://lloydkai.cn/categories/CS/"/>
    
    
    <category term="计算机专业知识" scheme="https://lloydkai.cn/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%B8%93%E4%B8%9A%E7%9F%A5%E8%AF%86/"/>
    
    <category term="电子产品" scheme="https://lloydkai.cn/tags/%E7%94%B5%E5%AD%90%E4%BA%A7%E5%93%81/"/>
    
  </entry>
  
  <entry>
    <title>MySQL学习笔记(零)数据库原理</title>
    <link href="https://lloydkai.cn/posts/database-principle/"/>
    <id>https://lloydkai.cn/posts/database-principle/</id>
    <published>2026-03-13T01:30:23.000Z</published>
    <updated>2026-04-23T01:48:22.122Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/lD4iJ2BjFNuQtoL.jpg" alt></p><blockquote><p>以下内容主体来自参考资料1的书，对于书中已有的概念、定义等的这里不再赘述</p></blockquote><h1>第一章：数据模型</h1><p>这一章主要考选填、简答题。重点背以下东西</p><p>data\database\DBMS的定义、特点及其包含关系</p><p>数据的独立性，逻辑和物理</p><p>数据模型的组成三要素</p><p>三级模式和两级映射是什么，如何工作的——<strong>两层映像的作用就是让上层的模式感受不到下层的变化，从而实现独立性</strong></p><p>数据控制：指的就是权限的授予和收回，</p><h2 id="为什么要解决数据冗余？">为什么要解决数据冗余？</h2><p><strong>数据冗余（Data Redundancy）</strong> 之所以被认为是产生数据不一致的根本原因，是因为它创造了<strong>同一信息多个独立副本</strong>并存的环境，却没有建立<strong>同步更新</strong>的机制，导致在更新时无法保证所有副本同时改变，从而引发矛盾</p><p>文件系统就具有数据冗余的缺点，无法保证当某一个副本更新的时候，其他与之关联的副本也随之更新，从而不能保证数据库的一致性。</p><h1>第二章：关系代数</h1><p>基本的五个关系运算</p><p>根据题目要求写查询的关系代数式——重点是多选、难点的</p><h2 id="为什么并、差、选择、投影、笛卡尔积是五个基本运算？">为什么并、差、选择、投影、笛卡尔积是五个基本运算？</h2><p>因为它们构成了一个<strong>完备集</strong>：这五个运算相互独立，且其他的关系代数运算（如交、连接、除等）都可以用这五个运算组合推导出来。</p><p>以下是常见的派生运算及其推导公式：</p><h4 id="1-交运算-cap">1. 交运算 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>∩</mo></mrow><annotation encoding="application/x-tex">\cap</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord">∩</span></span></span></span></h4><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>∩</mo><mi>S</mi><mo>=</mo><mi>R</mi><mo>−</mo><mo stretchy="false">(</mo><mi>R</mi><mo>−</mo><mi>S</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">R \cap S = R - (R - S)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∩</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></p><h4 id="2-连接运算-Join">2. 连接运算<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>⋈</mo></mrow><annotation encoding="application/x-tex">\Join</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.51em;vertical-align:-0.005em;"></span><span class="mrel">⋈</span></span></span></span></h4><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><msub><mo>⋈</mo><mi>θ</mi></msub><mi>S</mi><mo>=</mo><msub><mi>σ</mi><mi>θ</mi></msub><mo stretchy="false">(</mo><mi>R</mi><mo>×</mo><mi>S</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">R \Join_{\theta} S = \sigma_{\theta}(R \times S)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel">⋈</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></p><ol><li>先做 <strong>笛卡尔积</strong> ( <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>×</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">R \times S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span> )：把所有可能的组合都列出来。</li><li>再做 <strong>选择</strong> (<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mi>θ</mi></msub></mrow><annotation encoding="application/x-tex">\sigma_{\theta}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">θ</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> )：只保留那些满足连接条件 ( <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>θ</mi></mrow><annotation encoding="application/x-tex">\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span></span> ) 的组合。</li><li>自然连接可以在此基础上加上投影去掉重复的同名列。</li></ol><h4 id="3-除运算-div">3. 除运算<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>÷</mo></mrow><annotation encoding="application/x-tex">\div</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">÷</span></span></span></span></h4><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>R</mi><mo>÷</mo><mi>S</mi><mo>=</mo><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo><mo>−</mo><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mo stretchy="false">(</mo><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo><mo>×</mo><mi>S</mi><mo stretchy="false">)</mo><mo>−</mo><mi>R</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">R \div S = \pi_{A}(R) - \pi_{A}((\pi_{A}(R) \times S) - R)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">((</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span></span></span></span><br>（假设 A 是 R 独有的属性集，B 是 S 的属性集，且<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mo>⊆</mo><mi>R</mi></mrow><annotation encoding="application/x-tex">B \subseteq R</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></p><ol><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>1</mn><mo>=</mo><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T1 = \pi_{A}(R)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span></span></span></span>：找出 R 中所有可能的候选值（如所有学生）。</li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mn>2</mn><mo>=</mo><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mo stretchy="false">(</mo><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo><mo>×</mo><mi>S</mi><mo stretchy="false">)</mo><mo>−</mo><mi>R</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">T2 = \pi_{A}((\pi_{A}(R) \times S) - R)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">((</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span></span></span></span>：<ul><li>先做笛卡尔积 ( <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>A</mi></msub><mo stretchy="false">(</mo><mi>R</mi><mo stretchy="false">)</mo><mo>×</mo><mi>S</mi></mrow><annotation encoding="application/x-tex">\pi_{A}(R) \times S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>)：让每个候选值与 S 中所有值配对（想象每个学生配上所有课程）。</li><li>减去 ( R )：去掉实际存在的配对，剩下的就是“缺失的配对”（如张三缺了数学课没选）。</li><li>投影 ( <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mi>A</mi></msub></mrow><annotation encoding="application/x-tex">\pi_{A}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> )：找出有缺失配对的候选者（有过缺课记录的学生）。</li></ul></li><li>( T1 - T2 )：从所有候选者中减去那些有缺失的人，剩下的就是拥有全部 S 的人。</li></ol><h2 id="实战讲解">实战讲解</h2><p>传统的集合运算并不要求所有的属性名字一样，只需要取值范围相同(域)即可。</p><p><strong>已知关系模式S(sno,sname,age,sex),SC(sno,cno,Grade),C(cno,cname,teacher)</strong></p><h3 id="查询至少选修1号课程和3号课程的学生号码">查询至少选修1号课程和3号课程的学生号码</h3><p>这种选修多个的一般用除法(<strong>除法的作用就是找出符合多个条件的元组</strong>)，得到符合多个条件的元组</p><p>而除法会消除相同的属性，这里就用课程号。</p><p>由题，得到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>σ</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><msup><mn>1</mn><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>∧</mo><mi>c</mi><mi>n</mi><mi>o</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><msup><mn>3</mn><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\sigma_{cno =&#x27;1&#x27; \land cno =&#x27;3&#x27;}(SC)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.328em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mtight"><span class="mord mtight">1</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mbin mtight">∧</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mtight"><span class="mord mtight">3</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span></span></span></span>  这样得到选择了1、3其中一个的元组，然后只投影cno即可</p><p>然后，用<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{sno,cno}(SC)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span></span></span></span> 除去投影的就可以得到结果了</p><p>最终就是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo>÷</mo><msub><mi>π</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><msub><mi>σ</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><msup><mn>1</mn><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>∨</mo><mi>c</mi><mi>n</mi><mi>o</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><msup><mn>3</mn><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{sno,cno}(SC) \div \pi_{cno}(\sigma_{cno =&#x27;1&#x27; \lor cno =&#x27;3&#x27;}(SC))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.328em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mtight"><span class="mord mtight">1</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mbin mtight">∨</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mtight"><span class="mord mtight">3</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">))</span></span></span></span></p><p>用SQL如何表示？我们可以用自连接实现，也就是重复使用SC表，一个SC表的课程是c1，另一个SC表的课程是c2,通过学号连接起来即可</p><p>数据库传统写法</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 使用自连接</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> sc1.Sno</span><br><span class="line"><span class="keyword">FROM</span> SC sc1,SC sc2</span><br><span class="line"><span class="keyword">WHERE</span> sc1.sno <span class="operator">=</span> sc2.sno </span><br><span class="line">  <span class="keyword">AND</span> sc1.Cno <span class="operator">=</span> C1 </span><br><span class="line">  <span class="keyword">AND</span> sc2.Cno <span class="operator">=</span> C2;</span><br></pre></td></tr></table></figure><p>MySQL标准写法</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 使用自连接</span></span><br><span class="line"><span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> sc1.Sno</span><br><span class="line"><span class="keyword">FROM</span> SC sc1</span><br><span class="line"><span class="keyword">INNER</span> <span class="keyword">JOIN</span> SC sc2 <span class="keyword">ON</span> sc1.Sno <span class="operator">=</span> sc2.Sno</span><br><span class="line"><span class="keyword">WHERE</span> sc1.Cno <span class="operator">=</span> C1 </span><br><span class="line">  <span class="keyword">AND</span> sc2.Cno <span class="operator">=</span> C2;</span><br></pre></td></tr></table></figure><p>或者用双重存在（比较适合大数据的时候）</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> sno</span><br><span class="line"><span class="keyword">FROM</span> S</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">EXISTS</span> (</span><br><span class="line">    <span class="keyword">SELECT</span> <span class="number">1</span> <span class="keyword">FROM</span> SC <span class="keyword">WHERE</span> sno <span class="operator">=</span> S.sno <span class="keyword">AND</span> cno <span class="operator">=</span> C1</span><br><span class="line">) <span class="keyword">AND</span> <span class="keyword">EXISTS</span> (</span><br><span class="line">    <span class="keyword">SELECT</span> <span class="number">1</span> <span class="keyword">FROM</span> SC <span class="keyword">WHERE</span> sno <span class="operator">=</span> S.sno <span class="keyword">AND</span> cno <span class="operator">=</span> C2</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>如果是具体的课程名，查具体的学生名就要这样写</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow></msub><mo stretchy="false">(</mo><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo>÷</mo><msub><mi>π</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><msub><mi>σ</mi><mrow><mi>c</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mi>D</mi><msup><mi>B</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>∨</mo><mi>c</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mi>D</mi><msup><mi>S</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow></msub><mo stretchy="false">(</mo><mi>C</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>⋈</mo><mi>S</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{sname}(\pi_{sno,cno}(SC) \div \pi_{cno}(\sigma_{cname =&#x27;DB&#x27; \lor cname =&#x27;DS&#x27;}(C))  \bowtie S)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">nam</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">nam</span><span class="mord mathnormal mtight">e</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">D</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mbin mtight">∨</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">nam</span><span class="mord mathnormal mtight">e</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">D</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⋈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></p><p>先找出符合条件(用除法)的学生，然后再和表连接，最后投影</p><h3 id="查询至少选修两门课程的学生号码">查询至少选修两门课程的学生号码</h3><p>这里在上一问的基础上，不指定具体课程，应该怎么写呢？</p><p>我们可以想到，如果存在两个课程号不同，那么就至少选修了两门。</p><p>也就是说，相当于两个for循环，依次拿一个课程和其他课程一一比较，只要不同那么就满足条件，</p><p>在关系代数中要实现这样的效果，就需要借助<strong>笛卡尔积</strong>。</p><p>最终就是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><msub><mi>σ</mi><mrow><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo>=</mo><mo stretchy="false">[</mo><mn>4</mn><mo stretchy="false">]</mo><mo>∧</mo><mo stretchy="false">[</mo><mn>2</mn><mo stretchy="false">]</mo><mo mathvariant="normal">≠</mo><mo stretchy="false">[</mo><mn>5</mn><mo stretchy="false">]</mo></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo>×</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{sno}(\sigma_{[1] = [4] \land [2]\neq[5]}(SC \times SC))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">[</span><span class="mord mtight">1</span><span class="mclose mtight">]</span><span class="mrel mtight">=</span><span class="mopen mtight">[</span><span class="mord mtight">4</span><span class="mclose mtight">]</span><span class="mbin mtight">∧</span><span class="mopen mtight">[</span><span class="mord mtight">2</span><span class="mclose mtight">]</span><span class="mrel mtight"><span class="mrel mtight"><span class="mord vbox mtight"><span class="thinbox mtight"><span class="rlap mtight"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord mtight"><span class="mrel mtight"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel mtight">=</span></span><span class="mopen mtight">[</span><span class="mord mtight">5</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">))</span></span></span></span> 两个SC表通过sno连接，通过cno判断课程是否相同</p><p>用SQL语句如何实现呢？其实就是以每一个人为一组，统计其选课的数量，如果&gt;=2那么就满足条件，这种写法适合于动态数量的课程</p><p>示例如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> sno</span><br><span class="line"><span class="keyword">from</span> SC</span><br><span class="line"><span class="keyword">group</span> <span class="keyword">by</span> sno</span><br><span class="line"><span class="keyword">having</span> <span class="built_in">count</span>(<span class="keyword">distinct</span> cno)<span class="operator">&gt;=</span><span class="number">2</span></span><br></pre></td></tr></table></figure><p>假设要求至少选择c1-c4四门课，用group by的优势就很明显了</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> sno</span><br><span class="line"><span class="keyword">from</span> SC</span><br><span class="line"><span class="keyword">where</span> cno <span class="keyword">in</span> (c1,c2,c3,c4)</span><br><span class="line"><span class="keyword">group</span> <span class="keyword">by</span> sno</span><br><span class="line"><span class="keyword">having</span> <span class="built_in">count</span>(<span class="keyword">distinct</span> cno) <span class="operator">=</span> <span class="number">4</span>   <span class="comment">-- 这里要指定数量为4，因为where要求只能是这四门课中的一个</span></span><br></pre></td></tr></table></figure><h3 id="查询张三没有选修过的课程的课程号">查询张三没有选修过的课程的课程号</h3><p>首先，关系代数中不存在<code>!=</code>，没有<code>不符合</code>的说法</p><p>那么，解决思路就是正难则反，先找出张三选修过的课程，让所有的课程-张三选的=张三没有选的</p><p>所以，思路就清晰了。</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo>−</mo><msub><mi>π</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><msub><mi>σ</mi><mrow><mi>S</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><msup><mo>=</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mi>z</mi><mi>h</mi><mi>a</mi><mi>n</mi><mi>g</mi><mi>s</mi><mi>a</mi><msup><mi>n</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mo stretchy="false">)</mo><mo>⋈</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{cno}(SC) - \pi_{cno}(\sigma_{Sname = &#x27;zhangsan&#x27;  }(S)\bowtie SC)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mord mathnormal mtight">nam</span><span class="mord mathnormal mtight">e</span><span class="mrel mtight"><span class="mrel mtight">=</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span><span class="mord mathnormal mtight">han</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">a</span><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6828em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⋈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span></span></span></span></p><p>但是SQL语句中没有专门的减法，怎么实现呢？</p><p>常见的思路是转换逻辑，也就是说，张三没有选修的课程=不存在课程张三选修了</p><p>解答如下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> cno <span class="keyword">from</span> C</span><br><span class="line"><span class="keyword">where</span> <span class="keyword">not</span> <span class="keyword">exists</span>(</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> S,SC</span><br><span class="line">    <span class="keyword">where</span> S.sno <span class="operator">=</span> SC.sno</span><br><span class="line">    <span class="keyword">AND</span> SC.cno <span class="operator">=</span> C.cno</span><br><span class="line">    <span class="keyword">AND</span> S.sname <span class="operator">=</span> <span class="string">&#x27;张三&#x27;</span></span><br><span class="line">)</span><br></pre></td></tr></table></figure><h3 id="查询选修了全部课程的学生学号和姓名">查询选修了全部课程的学生学号和姓名</h3><p>关系代数：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>÷</mo></mrow><annotation encoding="application/x-tex">\div</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">÷</span></span></span></span> 的作用是实现<code>至少有</code>的功能，比如R<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>÷</mo></mrow><annotation encoding="application/x-tex">\div</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">÷</span></span></span></span>S,其中S有AB，R只要是S的父集就行</p><p>用关系代数很好实现,用除法找到符合条件的，然后连接就行</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo>÷</mo><msub><mi>π</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>C</mi><mo stretchy="false">)</mo><mo>⋈</mo><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>s</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{sno,cno}(SC) \div \pi_{cno}(C)\bowtie \pi_{sno,sname} (S)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⋈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">nam</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></p><p>但是SQL语句没有专门的除法，我们应该如何实现呢？</p><p>以下是两种思路</p><ul><li>方法1：如果一个学生选的课的数量，等于课程表中总的课程数量，那么他就选了全部课程</li><li>方法2：利用逻辑代数，选修了全部课程=没有一门课他没有选修</li></ul><p>方法1</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> S.sno, S.sname</span><br><span class="line"><span class="keyword">FROM</span> S</span><br><span class="line"><span class="keyword">WHERE</span> S.sno <span class="keyword">IN</span> (</span><br><span class="line">    <span class="keyword">SELECT</span> SC.sno</span><br><span class="line">    <span class="keyword">FROM</span> SC</span><br><span class="line">    <span class="keyword">GROUP</span> <span class="keyword">BY</span> SC.sno</span><br><span class="line">    <span class="keyword">HAVING</span> <span class="built_in">COUNT</span>(<span class="operator">*</span>) <span class="operator">=</span> (<span class="keyword">SELECT</span> <span class="built_in">COUNT</span>(<span class="operator">*</span>) <span class="keyword">FROM</span> C) <span class="comment">-- 选课数=全部的课程数</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure><p><strong>方法2需要多层嵌套，不建议使用</strong>。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> S.sno, S.sname</span><br><span class="line"><span class="keyword">FROM</span> S</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (</span><br><span class="line">    <span class="keyword">SELECT</span> <span class="operator">*</span></span><br><span class="line">    <span class="keyword">FROM</span> C</span><br><span class="line">    <span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (</span><br><span class="line">        <span class="keyword">SELECT</span> <span class="number">1</span></span><br><span class="line">        <span class="keyword">FROM</span> SC</span><br><span class="line">        <span class="keyword">WHERE</span> SC.sno <span class="operator">=</span> S.sno</span><br><span class="line">          <span class="keyword">AND</span> SC.cno <span class="operator">=</span> C.cno</span><br><span class="line">    )</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p><code>EXISTS</code> 只关心<strong>子查询是否返回行</strong>，不关心返回的具体内容。优化器在执行时，<strong>会把 <code>SELECT *</code> 自动优化成 <code>SELECT 1</code> 或 <code>SELECT 'any'</code></strong>，根本不会去实际获取数据</p><h4 id="具体讲解">具体讲解</h4><p><strong>S（学生表）</strong></p><table><thead><tr><th>sno</th><th>sname</th><th>age</th><th>sex</th></tr></thead><tbody><tr><td>1</td><td>张三</td><td>20</td><td>M</td></tr><tr><td>2</td><td>李四</td><td>21</td><td>F</td></tr><tr><td>3</td><td>王五</td><td>20</td><td>M</td></tr></tbody></table><p><strong>C（课程表）</strong></p><table><thead><tr><th>cno</th><th>cname</th><th>teacher</th></tr></thead><tbody><tr><td>A</td><td>数学</td><td>赵老师</td></tr><tr><td>B</td><td>英语</td><td>钱老师</td></tr></tbody></table><p><strong>SC（选课表）</strong></p><table><thead><tr><th>sno</th><th>cno</th><th>grade</th></tr></thead><tbody><tr><td>1</td><td>A</td><td>85</td></tr><tr><td>1</td><td>B</td><td>90</td></tr><tr><td>2</td><td>A</td><td>78</td></tr><tr><td>3</td><td>B</td><td>88</td></tr></tbody></table><p>总课程数 = 2（A、B）</p><p>找出<strong>选了全部课程</strong>的学生学号和姓名。</p><p>预期结果：只有 <strong>张三（sno=1）</strong> 选了 A 和 B。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="number">1</span></span><br><span class="line"><span class="keyword">FROM</span> SC</span><br><span class="line"><span class="keyword">WHERE</span> SC.sno <span class="operator">=</span> S.sno</span><br><span class="line">  <span class="keyword">AND</span> SC.cno <span class="operator">=</span> C.cno</span><br></pre></td></tr></table></figure><p>这个子查询的作用：<strong>检查某学生（S.sno）是否选了某门课（C.cno）</strong>。</p><hr><p>举例：当外层 S.sno = 1，C.cno = ‘A’</p><p>代入：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="number">1</span></span><br><span class="line"><span class="keyword">FROM</span> SC</span><br><span class="line"><span class="keyword">WHERE</span> SC.sno <span class="operator">=</span> <span class="number">1</span>      <span class="comment">-- 学生 1</span></span><br><span class="line">  <span class="keyword">AND</span> SC.cno <span class="operator">=</span> <span class="string">&#x27;A&#x27;</span>    <span class="comment">-- 课程 A</span></span><br></pre></td></tr></table></figure><p>从 SC 表中找：</p><table><thead><tr><th>sno</th><th>cno</th><th>grade</th></tr></thead><tbody><tr><td>1</td><td>A</td><td>85</td></tr><tr><td>1</td><td>B</td><td>90</td></tr></tbody></table><p>→ 找到一行（sno=1, cno=A）<br>→ 子查询返回 <strong>1 行</strong>（内容是 1）<br>→ <strong>存在</strong>（EXISTS 为 TRUE）</p><hr><p>举例：当外层 S.sno = 1，C.cno = ‘B’</p><p>找 SC 表：</p><table><thead><tr><th>sno</th><th>cno</th><th>grade</th></tr></thead><tbody><tr><td>1</td><td>A</td><td>85</td></tr><tr><td>1</td><td>B</td><td>90</td></tr></tbody></table><p>→ 找到一行（sno=1, cno=B）<br>→ <strong>存在</strong></p><hr><p>举例：当外层 S.sno = 2，C.cno = ‘B’</p><p>找 SC 表：</p><table><thead><tr><th>sno</th><th>cno</th><th>grade</th></tr></thead><tbody><tr><td>2</td><td>A</td><td>78</td></tr></tbody></table><p>→ 没有 sno=2 且 cno=B 的行<br>→ <strong>不存在</strong>（EXISTS 为 FALSE）</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span></span><br><span class="line"><span class="keyword">FROM</span> C</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (  <span class="comment">-- 最内层子查询 )</span></span><br></pre></td></tr></table></figure><p>这一层的逻辑：<br><strong>对于某学生 S.sno，遍历所有课程 C.cno，看是否存在一门课，这个学生没有选。</strong></p><hr><p>对学生 1（sno=1）执行这一层</p><p><strong>循环 C 表：</strong></p><ul><li>课程 A：最内层查询（sno=1, cno=A）→ 存在（TRUE）<br><code>NOT EXISTS (TRUE)</code> → FALSE → <strong>不保留 A</strong></li><li>课程 B：最内层查询（sno=1, cno=B）→ 存在（TRUE）<br><code>NOT EXISTS (TRUE)</code> → FALSE → <strong>不保留 B</strong></li></ul><p>结果：<strong>没有课程被保留</strong><br>→ 这一层子查询返回 <strong>空集（0 行）</strong></p><hr><p>对学生 2（sno=2）执行这一层</p><p><strong>循环 C 表：</strong></p><ul><li>课程 A：最内层查询（sno=2, cno=A）→ 存在（TRUE）<br><code>NOT EXISTS (TRUE)</code> → FALSE → <strong>不保留 A</strong></li><li>课程 B：最内层查询（sno=2, cno=B）→ 不存在（FALSE）<br><code>NOT EXISTS (FALSE)</code> → TRUE → <strong>保留 B</strong></li></ul><p>结果：<strong>保留课程 B</strong><br>→ 这一层子查询返回 <strong>1 行</strong>（B 这一行）</p><hr><p>对学生 3（sno=3）执行这一层</p><p><strong>循环 C 表：</strong></p><ul><li>课程 A：最内层查询（sno=3, cno=A）→ 不存在（FALSE）<br><code>NOT EXISTS (FALSE)</code> → TRUE → <strong>保留 A</strong></li><li>课程 B：最内层查询（sno=3, cno=B）→ 存在（TRUE）<br><code>NOT EXISTS (TRUE)</code> → FALSE → <strong>不保留 B</strong></li></ul><p>结果：<strong>保留课程 A</strong><br>→ 这一层子查询返回 <strong>1 行</strong>（A 这一行）</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> S.sno, S.sname</span><br><span class="line"><span class="keyword">FROM</span> S</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (  <span class="comment">-- 中间层子查询 )</span></span><br></pre></td></tr></table></figure><p>这一层的逻辑：<br><strong>筛选出那些“中间层子查询返回空集”的学生。</strong></p><hr><h5 id="对学生-1（sno-1）">对学生 1（sno=1）</h5><p>中间层子查询结果：<strong>空集（0 行）</strong><br><code>NOT EXISTS (空集)</code> → TRUE（因为不存在任何他没选的课）<br>→ <strong>保留学生 1</strong></p><hr><h5 id="对学生-2（sno-2）">对学生 2（sno=2）</h5><p>中间层子查询结果：<strong>1 行（课程 B）</strong><br><code>NOT EXISTS (有 1 行)</code> → FALSE<br>→ <strong>不保留学生 2</strong></p><hr><h5 id="对学生-3（sno-3）">对学生 3（sno=3）</h5><p>中间层子查询结果：<strong>1 行（课程 A）</strong><br><code>NOT EXISTS (有 1 行)</code> → FALSE<br>→ <strong>不保留学生 3</strong></p><hr><p>结果</p><table><thead><tr><th>sno</th><th>sname</th></tr></thead><tbody><tr><td>1</td><td>张三</td></tr></tbody></table><p>✅ 正确！只有张三选修了全部课程。</p><p>注意看的时候要从内向外看，先看最内层，再结合看最内层和倒数第二层，依次类推。</p><h3 id="查询所有学生都选修的课程号和课程名">查询所有学生都选修的课程号和课程名</h3><p>看起来很复杂，如果通过C语言的话好像需要暴力遍历求解，但这其实是上一问将学生和课程调换了一下顺序</p><p>也就是说，让sno和cno的集合除以sno，其含义就是课程被所有的学生选修了</p><p>最终结果就是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>π</mi><mrow><mi>c</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>c</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow></msub><mo stretchy="false">(</mo><mi>C</mi><mo>⋈</mo><mo stretchy="false">(</mo><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>c</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mi>C</mi><mo stretchy="false">)</mo><mo>÷</mo><msub><mi>π</mi><mrow><mi>s</mi><mi>n</mi><mi>o</mi></mrow></msub><mo stretchy="false">(</mo><mi>S</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\pi_{cno,cname}(C\bowtie (\pi_{sno,cno}(SC) \div \pi_{sno}(S)))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">nam</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⋈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)))</span></span></span></span></p><h3 id="查询选修了1号学生选修的所有课程的学生的学号">查询选修了1号学生选修的所有课程的学生的学号</h3><p>用除法很好理解，但是用SQL呢？</p><p>找出这样的学生：<strong>不存在</strong>一门1号学生选修的课程，而<strong>该学生没有选修</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="keyword">DISTINCT</span> sno</span><br><span class="line"><span class="keyword">FROM</span> SC SC1</span><br><span class="line"><span class="keyword">WHERE</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (</span><br><span class="line">    <span class="comment">-- 找到1号学生选修的所有课程</span></span><br><span class="line">    <span class="keyword">SELECT</span> cno</span><br><span class="line">    <span class="keyword">FROM</span> SC SC2</span><br><span class="line">    <span class="keyword">WHERE</span> SC2.sno <span class="operator">=</span> <span class="string">&#x27;1&#x27;</span></span><br><span class="line">      <span class="keyword">AND</span> <span class="keyword">NOT</span> <span class="keyword">EXISTS</span> (</span><br><span class="line">          <span class="comment">-- 检查当前学生是否选修了这门课</span></span><br><span class="line">          <span class="keyword">SELECT</span> <span class="number">1</span></span><br><span class="line">          <span class="keyword">FROM</span> SC SC3</span><br><span class="line">          <span class="keyword">WHERE</span> SC3.sno <span class="operator">=</span> SC1.sno</span><br><span class="line">            <span class="keyword">AND</span> SC3.cno <span class="operator">=</span> SC2.cno</span><br><span class="line">      )</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h3 id="exist的使用问题">exist的使用问题</h3><p>在SQL中，<code>EXISTS</code>子查询一定要通过某种方式引用外部查询的表，否则就变成了一个固定的布尔值判断</p><h1>第三章：SQL语句</h1><p><strong>特性</strong>：说 SQL 是“非格式化”的，主要是因为它是<strong>面向集合的描述性语言</strong>，而不是<strong>面向过程的步骤式语言</strong>。告诉计算机我要得到什么样的结果，至于怎么实现我不管。</p><h2 id="DDL、DML、DCL、DQL的区别和典型语句">DDL、DML、DCL、DQL的区别和典型语句</h2><h3 id="1-DDL（数据定义语言）">1. DDL（数据定义语言）</h3><ul><li><strong>定义：</strong> 用于<strong>定义、修改或删除数据库中的对象结构</strong>（如数据库、表、视图、索引等）。也就是说<strong>处理对象是表，索引这种的就是DDL</strong>。</li><li><strong>典型语句：</strong> 比如<code>create table</code> <code>drop index</code></li><li>特殊：audit语句是DDL</li></ul><h3 id="2-DML（数据操作语言）">2. DML（数据操作语言）</h3><ul><li><strong>定义：</strong> 用于操作数据库中存储的实际数据。</li><li><strong>典型语句：</strong> 插入删除和更改<code>insert delete update</code> 处理的对象是元组，实际的数据</li></ul><h3 id="3-DCL（数据控制语言）">3. DCL（数据控制语言）</h3><ul><li><strong>定义：</strong> 用于控制数据库的<strong>访问权限、用户权限和事务</strong>。涉及到授权的就是DCL</li><li><strong>典型语句：</strong><code>CREATE USER</code> / <code>DROP USER</code>：创建/删除用户 <code>grant revoke</code> 授权和回收权限等</li></ul><h3 id="4-DQL（数据查询语言）">4. DQL（数据查询语言）</h3><ul><li><strong>定义：</strong> 专门用于从数据库中查询数据。但在严格分类中单独列为DQL，因为它只负责查询，不修改数据。</li><li><strong>典型语句：</strong> <code>select</code> 语句</li></ul><hr><h2 id="通用分析方法">通用分析方法</h2><blockquote><p>就是要用分析英语长难句的方法分析实际需求，然后转为正确的sql语句</p><p><strong>三段论</strong>，如果有从句也同样按照此方法分析</p></blockquote><p>比如:查询所有年龄在20岁以下的学生姓名及其年龄</p><ol><li>首先分析查的是什么——姓名、年龄</li><li>然后从哪里查——学生表</li><li>查询条件是什么——age&lt;20</li></ol><p>最后基本上是补充限制条件(比如distinct防止重复、取别名等)、从后往前写，然后按照格式调整顺序即可</p><p>这里就是<code>where age &lt; 20</code> <code>from Student</code>  <code>select name,age</code></p><p>组合为</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> name, age <span class="keyword">from</span> Student <span class="keyword">where</span> age <span class="operator">&lt;</span> <span class="number">20</span>;</span><br></pre></td></tr></table></figure><p>如果涉及到分组，select后面只能跟被分组的属性或者是聚合函数，并且只能使用having作为限制条件而不能使用where。</p><h2 id="查询">查询</h2><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">&lt;</span>属性名<span class="operator">&gt;</span></span><br></pre></td></tr></table></figure><p>表明你要查的是什么,这里的属性名可以是表达式，也可以是表中没有的(比如字符串等)</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> <span class="operator">&lt;</span>表名或者视图名<span class="operator">&gt;</span></span><br></pre></td></tr></table></figure><p>从哪一个表(视图)中查</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">where</span> <span class="operator">&lt;</span>条件<span class="operator">&gt;</span></span><br></pre></td></tr></table></figure><p>查询记录所需要符合的条件</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">group</span> <span class="keyword">by</span> <span class="operator">&lt;</span>列名<span class="operator">&gt;</span></span><br></pre></td></tr></table></figure><p>查完之后按照哪一列分组，然后再展示</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">order</span> <span class="keyword">by</span> <span class="operator">&lt;</span>列名<span class="operator">&gt;</span></span><br></pre></td></tr></table></figure><p>最后给记录排序的时候按照哪一列排序，升序还是降序(默认升序)</p><h3 id="查询的背后">查询的背后</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> name,age</span><br><span class="line"><span class="keyword">from</span> student,sc</span><br><span class="line"><span class="keyword">where</span> student.sno <span class="operator">=</span> sc.sno <span class="keyword">and</span> sc.cno <span class="operator">=</span> <span class="string">&#x27;1&#x27;</span>;</span><br></pre></td></tr></table></figure><p>在查询的背后，首先用<code>student.sno = sc.sno</code> 将两个表合成一张大表，然后在此表的基础上选择符合条件的元组。</p><h2 id="常考的SQL语句">常考的SQL语句</h2><p>剩下的见书，常考的还有创建表、字符串的模糊匹配、嵌套查询、更新、插入、定义视图，见到一个查一个</p><h2 id="视图的使用">视图的使用</h2><p><strong>视图可不可以更新？答案是可以，也不可以。</strong></p><p>说视图可以更新，是因为对视图的更新最终要转化为对基本表的更新，如果对视图的更新(比如将所有成绩&gt;90的再+5)可以被正确转化为基本表的更新，那么就可以。</p><p>说视图不可以更新，比如一个视图的属性是平均成绩，想要更新为90，但是无法唯一转化为基本表的更新，所以视图不可更新。</p><h2 id="实战讲解-v2">实战讲解</h2><p>注意只有分组了之后才能使用having,where语句中不能出现聚集函数</p><p><code>HAVING</code> 的语法规则：<strong>只能使用「分组字段」或「聚合函数（count ()/sum ()/avg () 等）」作为判断条件</strong></p><p>WHERE 分组前过滤行，HAVING 分组后过滤组</p><p>还有一点就是and前后语句的顺序问题</p><p><strong>虽然可以调换顺序，但建议按照逻辑清晰的方式排列条件，比如先写连接条件，后写过滤条件，这样可以提高代码的可读性。</strong></p><h3 id="复杂的查询语句">复杂的查询语句</h3><p>执行顺序（死记）：<code>from</code> → <code>where</code> → <code>group by</code> → <code>having</code>→ <code>select</code></p><p>比如：统计各科不及格超过3的学生的人数——逻辑理解（通俗）：先把「不及格的成绩挑出来」，再「按学号分组」，最后「数每个组有多少个不及格的科目」，超过3的才选择，没有超过3的不展示。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> sno, <span class="built_in">count</span>(<span class="operator">*</span>)  </span><br><span class="line"><span class="keyword">from</span> sc </span><br><span class="line"><span class="keyword">where</span> grade <span class="operator">&lt;</span> <span class="number">60</span> </span><br><span class="line"><span class="keyword">group</span> <span class="keyword">by</span> cno</span><br><span class="line"><span class="keyword">having</span> <span class="built_in">count</span>(<span class="operator">*</span>)<span class="operator">&gt;</span><span class="number">3</span>;</span><br></pre></td></tr></table></figure><h3 id="空值的使用提醒">空值的使用提醒</h3><p>SQL 中判断字段是否为 NULL，<strong>唯一正确写法</strong>：<code>字段 IS NULL</code> / <code>字段 IS NOT NULL</code>；</p><p>NULL 是「未知值」，不能用 <code>=</code>/<code>!=</code>/<code>&lt;</code>/<code>&gt;</code> 等普通运算符匹配，这是 SQL 的语法铁律，用字段 + 运算符 + 比较值查不到任何值。</p><h1>第四章：数据库安全性</h1><p>主要出选填、简答题</p><p>背安全级别划分,还有以下的SQL语句</p><h2 id="授权和回收权利">授权和回收权利</h2><ol><li>授予什么权利</li><li>针对什么对象</li><li>给谁</li></ol><p>ex:在视图上授予王平查询学生表成绩的权利</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">grant</span> <span class="keyword">select</span>(grade) # 权利</span><br><span class="line"><span class="keyword">on</span> <span class="keyword">view</span> student # 对象</span><br><span class="line"><span class="keyword">to</span> WangPing # 用户</span><br></pre></td></tr></table></figure><p>有时候题目还要求使用WITH GRANT OPTION或者是级联等，注意</p><h2 id="审计">审计</h2><ol><li>对什么操作审计</li><li>针对哪一个表</li></ol><p>ex:对修改sc表的结构及其数据的操作进行审计</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">audit <span class="keyword">alter</span>,<span class="keyword">update</span> # 操作</span><br><span class="line"><span class="keyword">on</span> sc # 对象</span><br></pre></td></tr></table></figure><h1>第五章：数据库完整性</h1><blockquote><p>[!NOTE]</p><p>注意为了和实际应用相契合，这里统一用<strong>键</strong>指代<strong>码</strong>。</p></blockquote><p>三个完整性定义要背，同时题目喜欢考在创建表的时候限制主键和外键、属性的范围和要求等，SQL也要会写</p><h2 id="实体完整性">实体完整性</h2><p>就是主键的问题，唯一非空</p><h2 id="参照完整性——外键">参照完整性——外键</h2><p>简单来说，就是<strong>参照的</strong>一旦改动与被参照的不一致，就拒绝，<strong>被参照的</strong>改变要根据策略做出回应，是拒绝还是级联更新还是置空。</p><h2 id="用户定义完整性">用户定义完整性</h2><p>就是数据要符合要求，比如年龄不能有小数，性别只有两个等。</p><p>用sql语句规定其完整性，比如<code>NOT NULL</code> 不能为空，<code>Sex CHAR(2) CHECK(Sex IN('男','女'))</code> 性别只有两个</p><p>常见的有<code>NOT NULL</code> <code>UNIQUE</code> <code>CHECK</code></p><p>当然用的最多的就是<code>CONSTRAINT</code>语句</p><p>总结：三大完整性区别</p><p>实体：既然实际存在，那么就不为空</p><p>参照：外键为空或一致</p><p>定义：自行规定的取值范围。</p><h2 id="断言和触发器">断言和触发器</h2><p>断言类似各个计算机语言的assert,</p><p>而触发器相当于JavaScript的事件监听和触发</p><p>触发器的写法（一般的考试不会考，但是实际应用还是挺多的）</p><p><strong>实际案例</strong>：在学生管理系统数据库中创建一个触发器，当向学生选课表中插入记录时，检查该记录的学号在学生表中是否存在，检查该记录的课程号在课表中是否存在，以及选课成绩是否在0到100范围内，如果有一项为否，则不允许插入。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建触发器（MySQL语法）</span></span><br><span class="line">DELIMITER $$</span><br><span class="line"></span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TRIGGER</span> trg_check_insert_sc</span><br><span class="line">BEFORE <span class="keyword">INSERT</span> <span class="keyword">ON</span> SC</span><br><span class="line"><span class="keyword">FOR</span> <span class="keyword">EACH</span> <span class="type">ROW</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line">    <span class="keyword">DECLARE</span> student_exists <span class="type">INT</span>;</span><br><span class="line">    <span class="keyword">DECLARE</span> course_exists <span class="type">INT</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 检查学号是否存在</span></span><br><span class="line">    <span class="keyword">SELECT</span> <span class="built_in">COUNT</span>(<span class="operator">*</span>) <span class="keyword">INTO</span> student_exists <span class="comment">-- 把查询出来的结果写入student_exists</span></span><br><span class="line">    <span class="keyword">FROM</span> Student</span><br><span class="line">    <span class="keyword">WHERE</span> Sno <span class="operator">=</span> NEW.Sno; <span class="comment">-- 默认新插入的一行为new</span></span><br><span class="line">    </span><br><span class="line">    IF student_exists <span class="operator">=</span> <span class="number">0</span> <span class="keyword">THEN</span></span><br><span class="line">        SIGNAL <span class="keyword">SQLSTATE</span> <span class="string">&#x27;45000&#x27;</span></span><br><span class="line">        <span class="keyword">SET</span> MESSAGE_TEXT <span class="operator">=</span> <span class="string">&#x27;错误：学号不存在于学生表中！&#x27;</span>;</span><br><span class="line">    <span class="keyword">END</span> IF;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 检查课程号是否存在</span></span><br><span class="line">    <span class="keyword">SELECT</span> <span class="built_in">COUNT</span>(<span class="operator">*</span>) <span class="keyword">INTO</span> course_exists</span><br><span class="line">    <span class="keyword">FROM</span> Course</span><br><span class="line">    <span class="keyword">WHERE</span> Cno <span class="operator">=</span> NEW.Cno;</span><br><span class="line">    </span><br><span class="line">    IF course_exists <span class="operator">=</span> <span class="number">0</span> <span class="keyword">THEN</span></span><br><span class="line">        SIGNAL <span class="keyword">SQLSTATE</span> <span class="string">&#x27;45000&#x27;</span></span><br><span class="line">        <span class="keyword">SET</span> MESSAGE_TEXT <span class="operator">=</span> <span class="string">&#x27;错误：课程号不存在于课程表中！&#x27;</span>;</span><br><span class="line">    <span class="keyword">END</span> IF;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">-- 检查成绩是否在0-100范围内</span></span><br><span class="line">    IF NEW.Score <span class="operator">&lt;</span> <span class="number">0</span> <span class="keyword">OR</span> NEW.Score <span class="operator">&gt;</span> <span class="number">100</span> <span class="keyword">THEN</span></span><br><span class="line">        SIGNAL <span class="keyword">SQLSTATE</span> <span class="string">&#x27;45000&#x27;</span></span><br><span class="line">        <span class="keyword">SET</span> MESSAGE_TEXT <span class="operator">=</span> <span class="string">&#x27;错误：成绩必须在0-100范围内！&#x27;</span>;</span><br><span class="line">    <span class="keyword">END</span> IF;</span><br><span class="line"><span class="keyword">END</span>$$</span><br><span class="line"></span><br><span class="line">DELIMITER ;</span><br></pre></td></tr></table></figure><h1>第六章：关系数据库理论</h1><p>要解决的问题就是insert、update和delete的异常以及冗余的数据，通过合理规划依赖(也就是<strong>如何更好的设计表</strong>)，实现更好的数据库维护</p><p>这个思想其实与函数的单一性功能非常相似，也就是一张表“只干一件事”，把复杂的表拆分成几个简单的表，这样有助于更好维护数据库。</p><h2 id="范式-Normal-Form-NF">范式(Normal Form-NF)</h2><p><strong>定义</strong>：符合某种级别的关系模式的集合</p><p><strong>什么叫平凡</strong>？简单来说就是“大”推“小”，比如(Sno,Cno)→Cno,被推导出来的属性本就属于主动推导的一方(子集)，所以称为平凡的函数依赖</p><p><strong>1NF</strong>：不可分</p><p><strong>2NF</strong>：非主完全依赖于<strong>任意</strong>候选码(如果能推出多个，那么每一个都要满足)</p><p><strong>3NF</strong>：非主不存在对候选键的传递依赖。也就是<strong>消除非主属性的传递依赖</strong>，解决方法一般是：拆表</p><p>对于比较复杂的关系、依赖和隐蔽的传递依赖，需要通过定义判断</p><p>即R 满足 3NF，如果对 F 中每个函数依赖 X→Y（其中 Y 不在 X 中）：<strong>X 是超键或者Y 的每个属性都是主属性（属于某个候选键）</strong>。</p><p>然后对于隐藏的传递依赖，把所有候选键写出来，然后看能不能<strong>传递推导推出</strong>非主属性，都不能则说明是3NF</p><p><strong>BCNF</strong>：X推出Y，Y不属于X（<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>→</mo><mi>Y</mi><mo separator="true">,</mo><mi>Y</mi><mo>⊈</mo><mi>X</mi></mrow><annotation encoding="application/x-tex">X\rightarrow Y,Y\nsubseteq X</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0966em;vertical-align:-0.3027em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⊈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span>)且X必须是键（书本上说的是除了X之外没有决定性因素，X不能是键的一部分)。换句话说就是要<strong>消除主属性对码的部分函数依赖和传递函数依赖</strong>。</p><p><strong>此时BCNF基本消除了insert和delete异常</strong>，但是没有解决冗余问题</p><p><strong>多值依赖</strong></p><p>用例子来解释：【例】关系Teaching(C,T,B)中(C是课程，T是老师，B是参考书，一个老师可以教多个课程，一个课程可以由多个老师教，一个参考书可以供多个课程使用)，对于C的每一个值，T有一组值与之对应，而不论B取何值。因此T多值依赖于C，即C→→T。</p><p>表示为(C,B)→T,但是T与B没有关系。注意这里推出的是一组值而不是一个</p><p>比如对于(物理，大学物理)有一组值T{张三，李四}，而这组值只决定于物理©而不是B(大学物理)，哪怕改为(物理，量子力学)，对应的一组值仍然是{张三，李四},所以称为C→→T</p><p><strong>4NF</strong>：每一个非平凡多值依赖X→→Y，其中X都是键，解决了冗余问题。</p><p>如果画出图来，那么T与B的关系很像&quot;全相联映射&quot;。</p><h2 id="简单关系模式判断的方法">简单关系模式判断的方法</h2><p>比如关系模式STJ(S,T,J),分别表示学生、老师和课程，一个老师只教一门课，每门课有若干老师，某一个学生选定某门课，就对应一个固定的老师。</p><p>首先，先写出所有的依赖，这里是</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><mi>T</mi><mo stretchy="false">)</mo><mo>→</mo><mi>J</mi><mo separator="true">,</mo><mo stretchy="false">(</mo><mi>S</mi><mo separator="true">,</mo><mi>J</mi><mo stretchy="false">)</mo><mo>→</mo><mi>T</mi><mo separator="true">,</mo><mi>T</mi><mo>→</mo><mi>J</mi></mrow><annotation encoding="application/x-tex">(S,T)\rightarrow J,(S,J)\rightarrow T,T\rightarrow J</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.09618em;">J</span></span></span></span></p><p>然后一个个确定键，看相应的依赖，从第二范式开始判断是否符合</p><p>这里键分别是(S,T),(S,J)，注意T不是键。这里所有的属性都在候选键中，所以没有非主属性，因此满足2NF要求</p><p>同样没有码传递依赖，所以满足3NF</p><p>这里T决定J，J不包含于T，但是T不是码，所以不满足BCNF</p><p>综上，关系模式满足3NF</p><h3 id="2NF的判断问题">2NF的判断问题</h3><p>比如（Sno，Gno→Dno,(Sno,Dno)→Person,候选键是（Sno，Gno）,这个时候要多推导一下，由候选键推出Dno，Dno再结合主属性推出Person，对于Person来说是传递依赖，而不是部分函数依赖，因为(Sno,Dno)并不是候选键的真子集，不能称之为部分函数依赖，所以满足的是2NF，而不满足3NF。</p><h3 id="如何化为BCNF？">如何化为BCNF？</h3><p>以上题为例，有一个T→J,可以通过分解，把这个导致它不是bc范式的这个函数依赖给它分解出来。比如这里分成ST(S,T)和(T,J) 这样两个关系模式分别满足BCNF了。</p><h2 id="有多个候选键的关系模式范式判断">有多个候选键的关系模式范式判断</h2><p>有关系模式R(A,B,C,D,E)，函数依赖为F={A→C,BC→D,CD→A,AB→E}</p><p>首先，可以找到候选键为(A,B)和(B,C)，所有ABC都是主属性，DE是非主属性</p><p>是1NF吗？一般来说都是的</p><p>判断2NF，由定义——不存在非主属性对任意候选键的<strong>部分函数依赖</strong>，也就是说，对于这里的D和E，每一个都需要和候选键(A,B)、(B,C)进行判断，看是否有部分函数依赖，只有都没有的时候才是2NF</p><p>判断3NF，由定义——没有非主属性对候选键的<strong>传递依赖</strong>，注意传递函数依赖的格式是候选键→X→非主属性，其中X不是候选键.</p><p>或者用之前的定义判断，即R 满足 3NF，如果对 F 中每个函数依赖 X→Y（其中 Y 不在 X 中）：<strong>X 是超键或者Y 的每个属性都是主属性（属于某个候选键）</strong>。</p><h2 id="难点：公理系统">难点：公理系统</h2><p>闭包：比如<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>A</mi><mi>B</mi><msubsup><mo stretchy="false">)</mo><mi>F</mi><mo>+</mo></msubsup></mrow><annotation encoding="application/x-tex">(AB)^+_F</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.105em;vertical-align:-0.2935em;"></span><span class="mopen">(</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8115em;"><span style="top:-2.4065em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">F</span></span></span><span style="top:-3.1031em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2935em;"><span></span></span></span></span></span></span></span></span></span> 意思就是求在已知AB属性的情况下能够推出哪些属性。</p><p>这里不要求掌握推理过程和定义，直接放弃，以后有需要再学吧</p><h2 id="难点：无损连接分解和保持函数依赖分解">难点：无损连接分解和保持函数依赖分解</h2><p>这书看不下去，一堆公式没有例子，还是看国外版</p><h2 id="⭐⭐⭐模式分解">⭐⭐⭐模式分解</h2><blockquote><p>涉及到分库分表,我用一个实际例子来讲解如何分解表，以后工作分表、设计表的时候会很有帮助。</p></blockquote><p><strong>已知学生关系模式S(Sno,Sname,Sdept,Sdname,Course,Grade) 其中Sno为学号，Sname为学生名字，Sdept为系名，Sdname为系主任名字，Course为课程名，Grade为成绩</strong></p><ol><li>写出关系模式S的基本函数依赖和主键</li><li>原关系S为第几范式？为什么？请说明如何分解为高一级的范式</li><li>请在(2)的基础上分解为高一级的范式，并说明为什么？</li></ol><p>1)<strong>首先看当某一个属性(或者一组)确定的时候，另一个属性是否唯一确定</strong></p><p>比如当学号确定的时候，学生名字就唯一确定，则有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><mi>n</mi><mi>o</mi><mo>→</mo><mi>S</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">Sno \rightarrow Sname</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span></span></span></span></p><p>同理：当学号和课程同时确定时，才确定成绩，则有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi>S</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>C</mi><mi>o</mi><mi>u</mi><mi>r</mi><mi>s</mi><mi>e</mi><mo stretchy="false">)</mo><mo>→</mo><mi>G</mi><mi>r</mi><mi>a</mi><mi>d</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">(Sno,Course) \rightarrow Grade</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal">o</span><span class="mord mathnormal">u</span><span class="mord mathnormal">rse</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">G</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span></span></span></span></p><p>而当Sname确定的时候，无法确定Sdname，因为学生有可能重名，</p><p>依次类推分析…</p><p>得到基本函数依赖为</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><mi>n</mi><mi>o</mi><mo>→</mo><mi>S</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><mo separator="true">,</mo><mi>S</mi><mi>d</mi><mi>e</mi><mi>p</mi><mi>t</mi><mo>→</mo><mi>S</mi><mi>d</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><mo separator="true">,</mo><mi>S</mi><mi>n</mi><mi>o</mi><mo>→</mo><mi>S</mi><mi>d</mi><mi>e</mi><mi>p</mi><mi>t</mi><mo separator="true">,</mo><mo stretchy="false">(</mo><mi>S</mi><mi>n</mi><mi>o</mi><mo separator="true">,</mo><mi>C</mi><mi>o</mi><mi>u</mi><mi>r</mi><mi>s</mi><mi>e</mi><mo stretchy="false">)</mo><mo>→</mo><mi>G</mi><mi>r</mi><mi>a</mi><mi>d</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">Sno \rightarrow Sname,Sdept \rightarrow Sdname,Sno \rightarrow Sdept,(Sno,Course) \rightarrow Grade</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">pt</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">d</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">pt</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord mathnormal">o</span><span class="mord mathnormal">u</span><span class="mord mathnormal">rse</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">G</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span></span></span></span></p><p><strong>主键就是当某一个或者一组属性确定的时候，可以唯一确定一条记录(元组)</strong></p><p>这里主键就是(Sno,Course)，而且<strong>缺一不可</strong>。</p><p><strong>2)从1NF开始分析</strong></p><p>属性不可再分吗？是，那么就满足第一范式(1NF)</p><p>非主属性完全依赖于任意候选码？这里非主属性就是不属于候选码的属性，候选码是键，可以唯一确定一条记录。</p><p>这里候选码就是主键(Sno,Course),其他的属性就是非主属性，而根据1) Sname只需要Sno就可以确定，不需要Course，所以为否。</p><p>因此，这个模式为1NF</p><p><strong>那么如何分解呢？</strong></p><p>出问题的地方就是Course作为了主键的一部分，而Sname、Sdept都是不依赖于Course的，所以解决问题的方法就是让Course远离Sname和Sdept。</p><p>因此我们可以分解为</p><p>S1(Sno,Sname,Sdept,Sdname)  S2(Sno,Course,Grade)</p><p>这样在每一个关系模式中，非主属性完全依赖于任意候选码，因此两个都是2NF</p><p><strong>3)分析2)S1得到这样的基本函数依赖</strong></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi><mi>n</mi><mi>o</mi><mo>→</mo><mi>S</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi><mo separator="true">,</mo><mi>S</mi><mi>n</mi><mi>o</mi><mo>→</mo><mi>S</mi><mi>d</mi><mi>e</mi><mi>p</mi><mi>t</mi><mo separator="true">,</mo><mi>S</mi><mi>d</mi><mi>e</mi><mi>p</mi><mi>t</mi><mo>→</mo><mi>S</mi><mi>d</mi><mi>n</mi><mi>a</mi><mi>m</mi><mi>e</mi></mrow><annotation encoding="application/x-tex">Sno \rightarrow Sname,Sno \rightarrow Sdept,Sdept \rightarrow Sdname</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">pt</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">pt</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">d</span><span class="mord mathnormal">nam</span><span class="mord mathnormal">e</span></span></span></span></p><p>非主属性存在对主键的依赖传递吗？发现Sno可以通过Sdept决定Sdname，因此存在函数依赖，所以不是3NF。</p><p><strong>那么如何分解呢？</strong></p><p>出问题的地方就是Sdept充当了桥梁，那么过河拆桥即可，将Sdept分别给Sno和Sdname</p><p>因此我们可以分解为</p><p>S1(Sno,Sname,Sdept)  S3(Sdept,Sdname)</p><p>这样在每一个关系模式中，非主属性不存在对主键的依赖传递，因此两个都是3NF</p><h1>第七章：数据库设计</h1><p>这部分<strong>实践要重于理论</strong>，也就是说，理论过一下就行，最终在做项目的过程中体会到设计的全过程就行。</p><p>计算机很多知识都是这样，先有工程实践，然后将工程实践抽象为知识。</p><h2 id="概念结构设计">概念结构设计</h2><p>这个是重点部分。</p><p>目前常见的设计方法是：画E-R图、画UML图等，理论上喜欢用E-R，而实际应用偏UML</p><p>一切以实际开发为准，这里因为复试需要就学习E-R模型</p><p>当E-R图画好之后，就是看图说话，把基本的依赖都写出来，这样再根据不同的范式要求设计表就是<strong>逻辑结构设计</strong>。</p><p>如何画E-R图呢？我画的E-R图见UML图</p><p>首先，当只要求画局部的E-R图时，可以适当省略无关信息(做题的要求)</p><p>比如学生有学号、姓名、性别、课程，一开始先将其作为属性，然后读题，<strong>如果课程还可以细分，那么就将课程作为实体并联系，同时把本来学生的课程名属性等归到课程的实体属性中，以免重复</strong>。同时也要标记对应关系，这涉及到下一步的转换。</p><h2 id="逻辑结构设计——如何将画完的E-R图转化为关系模式">逻辑结构设计——如何将画完的E-R图转化为关系模式</h2><p>首先，将所有实体都看作一个表，写其所有的属性。</p><p>然后(以下是一般情况)</p><p>首先分析1:1的关系：可以直接将关系的两个实体的键+关系的属性单独合成一张表，然后这两个实体自己各自作为一张表，或者是把联系的另一端(B)的键+属性并入到另一端(A)（<strong>这叫合并</strong>)，那么A中有自己的属性+B的键+关系的属性，B中就只有自己的属性</p><p>再分析1：n的关系：将1端的实体的键和n端的实体所有属性+关系的属性合成一张表放入n端中，1保持不变</p><p>再分析m：n的关系：把两端的键+联系的属性拿出来单独合成一张表，两端也作为独立的一张表</p><p>最后，如果有传递性的也要同理处理</p><h2 id="实战讲解-v3">实战讲解</h2><p>某工厂（包括厂名和厂长名）需要建立一个数据库，其语义如下：<br>1）一个厂内有多个车间，每个车间有车间号、车间主任姓名、地址和电话：<br>2）一个车间有多个工人，每个工人有职工号、姓名、年龄、性别和工种：<br>3）一个车间生产多种产品，产品有产品编号、产品名称、规格型号和价格；<br>4）一个车间生产多种零件，一个零件也可能为多个车间制造。零件有零件号、零件名、重量和价格.<br>5）一个产品由多种零件组成，一种零件也可装配出多种产品：<br>6）产品与零件均存入仓库中；<br>7）厂内有多个仓库，仓库有仓库号、仓库主任姓名和电话。<br>画出该数据库的E-R图。</p><p><strong>解答：</strong></p><p><img src="https://files.seeusercontent.com/2026/03/14/dB3z/MySQL_ERdrawio.png" alt="MySQL学习笔记(零)数据库原理_工厂数据库ER图.drawio.png"></p><p>对应转化为关系模式为(这里采取1：n合并或者单独构成一张表) <strong>结果不唯一</strong></p><p><strong>工厂</strong>(厂名，厂长名) 主键：(厂名)</p><p><strong>车间</strong>(车间号，车间主任姓名，地址，电话，厂名) 主键：(车间号) 外键：厂名 → 工厂(厂名)</p><p><strong>工人</strong>(职工号，姓名，年龄，性别，工种，车间号) 主键：(职工号) 外键：车间号 → 车间(车间号)</p><p><strong>仓库</strong>(仓库号，仓库主任姓名，电话，厂名)  主键：(仓库号)  外键：厂名 → 工厂(厂名)</p><p><strong>产品</strong>(产品编号，产品名称，规格型号，价格)  主键：(产品编号)</p><p><strong>零件</strong>(零件号，零件名，重量，价格)  主键：(零件号)</p><p><strong>生产产品</strong>(车间号，产品编号)  主键：(车间号，产品编号)  外键：车间号 → 车间(车间号)  外键：产品编号 → 产品(产品编号)</p><p><strong>制造零件</strong>(车间号，零件号)  主键：(车间号，零件号)  外键：车间号 → 车间(车间号)  外键：零件号 → 零件(零件号)</p><p><strong>产品组成</strong>(产品编号，零件号)  主键：(产品编号，零件号)  外键：产品编号 → 产品(产品编号)  外键：零件号 → 零件(零件号)</p><p><strong>存储产品</strong>(仓库号，产品编号)  主键：(仓库号，产品编号)  外键：仓库号 → 仓库(仓库号)  外键：产品编号 → 产品(产品编号)</p><p><strong>存储零件</strong>(仓库号，零件号)  主键：(仓库号，零件号)  外键：仓库号 → 仓库(仓库号)  外键：零件号 → 零件(零件号)</p><h1>第八章：嵌入式SQL</h1><p>目前只考了存储过程</p><h2 id="存储过程和函数">存储过程和函数</h2><p>示例：创建一个过程，将学号为s1,课程为c1的成绩修改为g1</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">OR</span> REPLACE <span class="keyword">PROCEDURE</span> PROC3</span><br><span class="line">(</span><br><span class="line">    S1 <span class="type">CHAR</span>(<span class="number">8</span>),</span><br><span class="line">    C1 <span class="type">VARCHAR</span>(<span class="number">10</span>),</span><br><span class="line">    G1 <span class="type">SMALLINT</span>,</span><br><span class="line">)</span><br><span class="line"><span class="keyword">AS</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"><span class="keyword">UPDATE</span> SC</span><br><span class="line"><span class="keyword">SET</span> GRADE <span class="operator">=</span> G1</span><br><span class="line"><span class="keyword">WHERE</span> S#<span class="operator">=</span>S1 <span class="keyword">AND</span> CN<span class="operator">=</span>C1</span><br><span class="line"><span class="keyword">END</span></span><br></pre></td></tr></table></figure><h1>第九章：关系查询处理和优化</h1><p>P书285页，这里是重点，以后无论是设计还是查询都要学会其中的方法，这也是区分一般程序员和优秀程序员的关键知识。</p><p>背查询处理的四个步骤，了解查询优化算法、代数优化的方法</p><h2 id="语法树的查询优化过程">语法树的查询优化过程</h2><ol><li>首先拿到关系代数式子写成语法树形式</li><li>可以下移的<strong>选择</strong>往下移到底</li><li>把不需要的列投影去掉</li><li>分组：一个笛卡尔积（二元运算）分为一组</li></ol><h1>第十章：数据库恢复技术</h1><p>掌握事务的四特点、四种故障、检查点。</p><h2 id="为什么要设置日志文件？">为什么要设置日志文件？</h2><p>是为了记录对数据库中数据的每一次更新操作，从而DBMS可以根据日志文件进行事务故障的恢复和系统故障的恢复，并可结合后援副本进行介质故障的恢复。</p><p>具体来说，比如事务中执行了insert语句，如果执行有误要回滚的时候，直接反过来执行相应的语句,比如这里就执行delete语句，把插入的”撤销“回去，</p><h1>第十一章：并发控制</h1><p>注意区分幻读和脏读——关键是脏读涉及到事务的撤销</p><p>S锁和X锁的相容关系、两段锁协议</p><p>目前还没有看到难的</p><h1>新技术篇</h1><p>等研究生的时候再学</p><h1>后续重点学习和补充的地方</h1><ul><li>在实际项目开发中复杂SQL语句的写法</li><li>大型项目的分库和分表涉及到的理论知识</li></ul><h1>参考资料</h1><ol><li>数据库系统概论/王珊,萨师煊编著.–5版.–北京：高等教育出版社,2014.9(2022.5重印)     ISBN 978-7-04-040664-1</li><li><a href="https://chat.deepseek.com/">deepseek </a>：用于生成database实践案例</li></ol>]]></content>
    
    
    <summary type="html">学习数据库的基本原理和理论知识，为后续学习MySQL等数据库打下坚实的基础</summary>
    
    
    
    <category term="MySQL" scheme="https://lloydkai.cn/categories/MySQL/"/>
    
    
    <category term="MySQL" scheme="https://lloydkai.cn/tags/MySQL/"/>
    
    <category term="计算机专业知识" scheme="https://lloydkai.cn/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E4%B8%93%E4%B8%9A%E7%9F%A5%E8%AF%86/"/>
    
  </entry>
  
  <entry>
    <title>考研经验帖</title>
    <link href="https://lloydkai.cn/posts/post-on-experience/"/>
    <id>https://lloydkai.cn/posts/post-on-experience/</id>
    <published>2026-01-18T01:10:23.000Z</published>
    <updated>2026-04-23T01:44:04.559Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/nTGQsyz47qmcHhx.jpg" alt></p><h1>个人背景</h1><p>本人为双非的应届生，由于自己职业规划不明确，直到大二下才确定自己的职业发展目标，自觉走机械这条路走不通，选择跨考计算机。<br>考虑到本人是双非院校+跨考debuff，就选择了广州的211——华南师范大学。初试390，一战上岸计算机学院软件工程学硕。</p><p>在本科期间没有科研经历，只有一个蓝桥杯省级二等奖，相当于没有，虽然有奖学金，但双非的成绩懂得都懂。年级排名前20%，六级500出头，有一定的学习基础。在大二的时候跟着网上的资源自学了一些C++、数据库、前端、Linux等，对408有一定的了解，至少不算是完全没学过，<strong>我个人认为这是我同一些跨考计算机同辈们最大的不同——我是认真学了一年计算机之后才作出的跨考决定，而不是简单的出于对本专业的厌恶或者是对计算机高薪的向往而作出的选择</strong>。</p><h1>择校经验</h1><p>这部分我给不了多少经验，我当时就想着如果要在计算机这一行发展，那么就只能去北上广深，对我来说湖北都是偏北方，所以我只考虑广州的学校，然后结合自己的背景，选择了一个偏保险的211，而广州只有暨南和华师这两个211。暨南是偏文科的，而且我要报考的是偏软件方向，而暨南没有，最后排除法就选择了华南师范大学。</p><h1>初试复习经验</h1><h2 id="政治">政治</h2><p>我在九月之前没有碰过政治，大量实践案例证明9月开始完全来得及，就我身边备考的那些人都是从10月开始复习政治，最后也考了70多，所以如果学习任务紧张的话，就不要在9月之前开政治，开了也没用。</p><p>我的学习路线是，先过一遍徐涛的强化课，最值得听的就是马原、毛概，历史学得好的不用看史纲，道法和新思想看视频意义不大，考场上都是考语感和理解的选择题。然后用小程序刷1000题、米鹏、腿姐的选择题，过了两遍背诵手册，最后刷肖四肖八选择题，米鹏六套卷，真题就上考场了。</p><p><strong>考后复盘</strong></p><ol><li>1000题更侧重于知识的全面复习，如果时间紧张确实没什么必要做。</li><li>真题很少出帽子题，更多的情况下是结合时政考你对某个知识的理解，在某种意义上就是靠语感选的，所以没有必要花大量时间在背诵手册上，眼睛过几遍就差不多了.</li><li>肖四前两套一定要背，不一定能压对，但是至少能让你有一定的语料，有话可写。后两套意义不大，我当时没有背，最后考试的时候发现真题考的主要就是前两套题目。</li><li>真题一定要做，而且要总结错误原因，比如绝对化、换主语等，真题是和模拟题不一样的。</li><li>在考前几天最好完整练习一套试卷，一般来说选择题在30min左右，大题每一个小问12-14min，一定要严格限制在14min以内，否则在考场上很有可能写不完。</li></ol><p>还有一个注意事项是，考场上政治考试的答题卡比你网上买的要稍微大一点，练习的时候按照自购的答题卡限制范围就没问题。</p><p>还有一个tip是：倒数第二大题道德与法治的答题范围大概是其他题目的3/4,所以你在背诵的时候这部分可以少背一点(笑)</p><h2 id="英语">英语</h2><p><strong>单词</strong></p><p>个人推荐用软件来背单词，不需要买单词书，也不要自己搞一个什么艾宾浩森遗忘曲线图表、乱七八糟的笔记本，直接刷背单词就行了。</p><p>在背单词的时候尽量看句子回答，就实际情况而言，<strong>大部分人不是不知道这个单词是什么意思，而是不知道在这个句子里面单词是什么意思</strong>，脱离句子背单词，就是无根之木。</p><p><strong>三小门</strong></p><p>这部分我是看的宋逸轩老师的网课，我建议是看老师的方法论，跟着先做几道题，剩下的就是自己限时实战做题。没必要花大量时间在这上面，在考场上这三部分大概率你是在最后1小时左右的时候写的，能够拿到及格分就是胜利。你像翻译这部分，不仅考英语，还考语文表达水平，这些都不是一朝一夕能提升的，能够短期提升的就是考试技巧和方法。</p><p><strong>阅读</strong></p><p>这部分我看的是唐迟老师的阅读方法论，唐迟老师的课有优点也有缺点，优点是对于一个题目能够从多个角度(主要是逻辑)去分析为什么这样选，确保选择的肯定性和正确性，缺点就是这个方法在某种意义上是<strong>建立在能够全文阅读并且大概理解的基础上的</strong>，如果你没有这种能力，可能唐迟老师不太适合你，一般我就建议基础差一点的跟颉斌斌老师学方法。</p><p>英语的真题是最重要的，建议每天都练习一套阅读，限制在18min左右。</p><p>至于作文，我推荐基础一般的跟石雷鹏，基础好的跟王晶婷，在大概九月份的时候开作文，每隔几天练习小作文或者大作文。到考前哪怕脑子没有记住，手也能记住。虽然大部分人吐槽石雷鹏的作文模板过于简单，我推荐他还是因为这个写作思路是通用的，你完全可以沿用相同的思路用不同的语法、句子来写，我自己就是用石雷鹏的思路，写王晶婷的句子。</p><p>至于时间，一般来说小作文18min，大作文36min，实际上如果平时练熟了的话大作文可以在25min左右写完，多出来的时间可以用于阅读，但是建议不要超过时间，否则后面就没有时间写三小门了。</p><p>考场的作答顺序，我推荐先写前两篇阅读，然后写小作文，再两篇阅读，再大作文，三小门，最后写完形。让写作和阅读交错避免疲劳。</p><h2 id="数学">数学</h2><p><strong>基础阶段</strong></p><p>我个人是非常推荐张宇🐙老师的高数18讲，讲的非常仔细。有些知识武忠祥老师没有讲但是张宇老师讲了，比如点绕曲线得到曲面方程的求法。</p><p>线性代数我全程跟着李永乐老师，但是就考研的趋势来看，最好还加上张宇的线代作为补充。</p><p>概率论与数理统计我非常推荐跟方浩，当你学了“刚好遇见你”求卷积，高山看海求复合期望的时候，就会意识到这些方法有多么巧妙。</p><p>张宇老师有一点可能不太好，就是有许多的二级结论和超纲的知识点，实际上在考场上用不到多少，很多都是事后的角度补充知识点，而且书写得太厚，容易把把握不到重点。</p><p><strong>强化阶段</strong></p><p>高数部分我强烈推荐武忠祥老师，对于知识、考点和方法的总结堪称一绝，我确实学到了许多的技巧和知识，也应用到了考场上。</p><p>张宇的课就是大力出奇迹，不管什么题，都是从定义、知识出发一步步解答，如果想考高分推荐张宇。</p><p>我推荐的做题册就是880和660,1000题太有张宇的风格，660是用来针对选填的，880非常贴近真题，因为很多就是真题的改编，当然也有很多题很难，不要灰心，一点点刷，反复多做几次，重要的是知识点而不是正确率。</p><p><strong>冲刺阶段</strong></p><p>这部分我在10月的时候开始做真题，注意在21年左右的时候是一个分水岭，前面的都是8选择6填空8大题，后面改革变成10选择6填空6大题，选填占80分。所以10-20年的可以做，零几年的选择做，重点是21年之后的，反复做。</p><p>在写完之后可以适当刷模拟题，主要是模拟考试情况，我个人推荐的选择题是李六，合工大有点过于难了，但是用选填查漏补缺还可以。</p><p>就考试情况来看，最最最重要的就是计算能力，很多人就是知识知道，但就是算不对，5分10分就没有了，一定在平时的时候练习限时做题目，不仅要算的快，而且要算的对。</p><h2 id="给跨考生的建议">给跨考生的建议</h2><p>首先，肯定你对计算机的热爱和敢于挑战的勇气，11408可是死亡组合，能和它相比的好像只有电气。</p><p>其次，在你复习之前，我有一些建议想和你说。</p><p><strong>408虽然看起来只有4本，但实际上并非如此</strong>。</p><p><strong>数据结构是默认你会C语言、C++的</strong>，虽然老师说考试只是涉及到C基本的语法，但是2025年考的内存分区，对于计算机的人来说在学C语言、Java的时候老师一定会提到，但是书上你是找不到知识点的，也就是说，<strong>408还会考计算机学生的基本素养</strong>，你要做的就是在备考前和备考时多多学习计算机的基本知识。</p><p><strong>计算机组成原理是建立在数字电路和汇编语言的基础上的</strong>，因为我是机械偏控制方向的，所以我都学过。如果你还没有学过，建议还是先学习一下这两门课程，否则看计组真的是在看天书。数字电路看一下速成课就差不多了，汇编建议跟王爽老师的《汇编语言》学，大概了解即可。</p><p>操作系统对于没有接触过基础架构的人来说更是抽象无比，我的建议是，可以跟着黑马快速学习和体验一下Linux操作系统，对内存管理、文件管理、进程等有一个感性的认识，这样再学操作系统才不会将大量的时间投入到概念的背诵，而是从底层逻辑明白这项技术为什么诞生，解决了什么样的问题。</p><p>计算机网络我建议跟湖科大，讲得一绝。至于做题我建议看王道咸鱼的“骚图”，一步步从底层讲这个数据是如何封装、选择、发送、应答和接收的。</p><p>如果你还有余力，我建议还可以学习离散数学和编译原理，主要是针对数据结构的选择题和应用题。</p><p>我的备考路线是：从三月份开始，第一轮跟着王道视频过一遍，然后写课后选择题，第二轮自己把书看一遍，自己画思维导图、看书和自己讲解知识点，然后把一轮的错题再做一遍，尝试做大题，在暑假的时候看王道的强化课。10月的时候跟湖科大的每日一题，用checklist记录遗忘的知识点并且复习，每天花4小时左右，一天学习数据结构和计算机网络，一天学习计算机组成原理和操作系统，这样不容易遗忘。</p><p>最后两个月一遍用真题模拟，一边做了王道和竟成的模拟卷，个人觉得王道的pv大题、选择，还有竟成的选择还是值得做的，主要是查漏补缺。</p><p><strong>考后复盘</strong></p><ol><li>每年408选择都会出一些王道书上没有的知识点，有时候并不算超纲，但是对于我这种跨考的来说，光是过完这四本书就竭尽全力了，没有多余的时间在读原教材上，所以建议对分数要求不高的不用花时间在回归教材上。对着大纲复习犹如海底捞针。</li><li>王道的课后大题除了pv的基本上没必要做，就只做真题</li><li>王道的强化课值得看，咸鱼会讲相关的知识给你串一遍，让你有一定的系统思维和知识贯通的感觉，结合他们的卷子和打卡表复习。</li><li><strong>408目前的趋势是：题目越来越难，大题字数越来越多</strong>。40个选择和7个大题要想在3小时写完是相当紧张的，平时就要限时写选择(1.5min一个),大题大概16-18min，而且也极其考验考生的阅读水平、知识迁移和计算机基本功的能力，可以这么说，以后跨考生会越来越难，这应该是国家的战略需要——高水平的计算机人才。</li></ol><h1>总结复盘</h1><h2 id="学习时间的合理规划">学习时间的合理规划</h2><p>在2-6月的时候，我基本上是7.30开始学数学，学4小时左右，吃饭+午休，然后下午1：00到5:30学4小时左右在408上，晚饭，再学2个小时数学，然后英语两个小时。一天下来就是12小时。基本没有放假休息。后面果然身体扛不住了，暑假回家休息了一个月，这期间每天学10小时左右。然后从9月开始学习时间在11小时上下，一直到考前。</p><p>我建议是学习时间在10-12小时，一周最好休一天或者一个时间段，否则身体一定扛不住的。</p><p>同时，建议没有必要的时候少带耳机等，我就是因为看视频听音乐带耳机过多，导致后期出现了耳鸣，一度想要放弃。好在最后还是缓解了。</p><p>我想说的是，<strong>适度原则，违背客观规律只会顾此失彼，得不偿失</strong>，当你的身体无法支撑你学习的时候，请马上停止，务必休息！考研只是一条路，但是生命只有一次！</p><h2 id="学习方法的复盘">学习方法的复盘</h2><p>个人认为比较好的学习方法是checklist，也就是回顾式复习——每一次的复习不是都要从第一章开始，而是从最薄弱的地方开始</p><p>示例如下，</p><p><img src="https://files.seeusercontent.com/2026/04/10/vr4U/_checklist_001.png" alt="考研经验帖_checklist_001"></p><p>也就是每天学习的时候把自己感觉比较困难的、易错的知识写成“待办”事项，然后学习之前就把checklist拿出来，对着题目用自己的话回答，如果答出来就勾选上并再过几天复习一次，复习时间间隔依次增大，如果答不上来就标记并适当增加复习次数，直到自己能流畅回答再开始下一个的学习，通过这个方法，我不仅记住了很多知识，并且学会了深入思考问题，让我在面对难题的时候游刃有余。</p><p>或者用图画的形式学习和复习知识，如下所示，<a href="http://xn--draw-p85fj2aw57icbzartcuw4g.io">使用的软件是draw.io</a>。</p><p><img src="https://files.seeusercontent.com/2026/04/10/faD1/_.jpg" alt="考研经验帖_函数栈帧"></p><p>408的知识很多很杂，你需要的不是一字不落的将所有内容背下来，而是用自己的方式理解并且用自己的话表达出来，图画+文字就是形和数的结合，前者直观后者入微，当你能像这样画出知识并且给自己或者他人讲一遍的时候，会记得又快又牢，这个方法的原理就是学习的金字塔——讲授给他人时知识的留存率是70%，而看视频看书知识的留存率是10%，所以在复习的时候可以多多尝试将知识讲给他人听，如果能够让那些不懂计算机的人都听懂了， 那么你才算是真的懂了。</p>]]></content>
    
    
    <summary type="html">以个人的实际经历为基础，给即将跨考408的同学提一些考研备考的建议。</summary>
    
    
    
    <category term="考研" scheme="https://lloydkai.cn/categories/%E8%80%83%E7%A0%94/"/>
    
    
    <category term="考研经验" scheme="https://lloydkai.cn/tags/%E8%80%83%E7%A0%94%E7%BB%8F%E9%AA%8C/"/>
    
  </entry>
  
  <entry>
    <title>基于51单片机的红外遥控切换数码管显示系统设计</title>
    <link href="https://lloydkai.cn/posts/51-SingleMachine/"/>
    <id>https://lloydkai.cn/posts/51-SingleMachine/</id>
    <published>2025-10-31T13:23:32.000Z</published>
    <updated>2026-04-23T01:43:00.347Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/G1CvfEijKStxwXl.jpg" alt></p><h1>基于51单片机的红外遥控切换数码管显示系统设计</h1><h2 id="一、项目背景">一、项目背景</h2><h3 id="1-1-设计背景">1.1 设计背景</h3><p>随着现代电子技术的快速发展，红外遥控技术因其抗干扰能力强、传输可靠、功耗低等优点，已经广泛应用于各种家用电器和电子设备中。红外遥控系统具有以下特点：</p><ul><li><strong>非接触式控制</strong>：无需物理连接,操作方便</li><li><strong>抗电磁干扰</strong>：红外线不易受到电磁信号的干扰</li><li><strong>安全性好</strong>：红外信号不会穿透墙壁，具有较好的保密性</li><li><strong>成本低廉</strong>：红外发射和接收器件价格低廉，易于集成</li></ul><h3 id="1-2-设计目的">1.2 设计目的</h3><p>本项目旨在设计并实现一个基于51单片机的红外遥控数码管显示系统，主要目的包括：</p><ol><li>掌握51单片机的基本编程方法和中断处理机制</li><li>理解红外遥控编码协议（NEC协议）的工作原理</li><li>学习数码管的动态扫描显示技术</li><li>培养嵌入式系统的软硬件协同设计能力</li></ol><h3 id="1-3-应用场景">1.3 应用场景</h3><p>该系统可应用于：</p><ul><li>教学实验平台，用于学习红外通信和单片机开发</li><li>简单的遥控显示设备原型开发</li><li>家用电器的遥控接收显示模块</li><li>智能家居控制系统的输入显示单元</li></ul><h3 id="1-4-红外遥控的原理">1.4 红外遥控的原理</h3><p>红外遥控是一种无线、非接触控制技术，具有抗干扰能力强，信息传输可靠，功耗低，成本低，易实现等显著优点，被诸多电子设备特别是家用电器广泛采用，并越来越多的应用到计算机系统中。</p><p>由于红外线遥控不具有像无线电遥控那样穿过障碍物去控制被控对象的能力，所以，在设计红外线遥控器时，不必要像无线电遥控器那样，每套(发射器和接收器)要有不同的遥控频率或编码(否则，就会隔墙控制或干扰邻居的家用电器)，所以同类产品的红外线遥控器，可以有相同的遥控频率或编码，而不会出现遥控信号“串门”的情况。这对于大批量生产以及在家用电器上普及红外线遥控提供了极大的方便。由于红外线为不可见光，因此对环境影响很小，再由红外光波动波长远小于无线电波的波长，所以红外线遥控不会影响其他家用电器，也不会影响临近的无线电设备。</p><p>红外遥控通信系统一般由红外发射装置和红外接收设备两大部分组成。</p><hr><h2 id="二、方案设计">二、方案设计</h2><h3 id="2-1-系统功能需求">2.1 系统功能需求</h3><p>本系统要求实现以下功能：</p><ol><li><strong>红外信号接收</strong>：系统能够接收标准NEC协议的红外遥控信号</li><li><strong>按键识别</strong>：识别红外遥控器的21个按键（0-20），每行3个按钮，共7行</li><li><strong>数码管显示</strong>：<ul><li>对于0-20号按键：显示对应的十进制数字（两位数码管）</li><li>对于其他按键：显示按键编码的十六进制值</li><li>始终显示&quot;H&quot;标识符，表示十六进制模式</li></ul></li></ol><h3 id="2-2-总体方案">2.2 总体方案</h3><p>系统采用模块化设计思想，主要分为以下几个模块：</p><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    graph LR    A[红外遥控器] --&gt;|红外信号| B[红外接收模块]    B --&gt;|电平信号| C[51单片机]    C --&gt;|段码&#x2F;位选| D[数码管显示模块]    style A fill:#e1f5ff    style B fill:#ffe1e1    style C fill:#fff4e1    style D fill:#e1ffe1  </pre></div><p><strong>核心控制器</strong>：STC89C52单片机（或兼容的51系列）</p><ul><li>主频：12MHz晶振</li><li>内存：8KB Flash，256B RAM</li><li>I/O口：充足，满足数码管和红外接收需求</li></ul><p><strong>系统工作流程</strong>：</p><ol><li>红外接收头接收遥控器发出的红外信号</li><li>信号经解调后输入单片机的外部中断0引脚（P3.2）</li><li>单片机解析NEC协议，提取控制码</li><li>根据控制码查表，确定按键编号</li><li>将结果转换为数码管段码</li><li>通过动态扫描方式驱动数码管显示</li></ol><h3 id="2-3-技术特点">2.3 技术特点</h3><ul><li><strong>中断驱动</strong>：采用外部中断方式接收红外信号，提高系统响应速度</li><li><strong>协议解析</strong>：完整实现NEC红外协议的引导码、数据位和校验机制</li><li><strong>动态显示</strong>：采用数码管动态扫描技术，节省I/O口资源</li><li><strong>模块化设计</strong>：代码按功能分层，便于维护和扩展</li></ul><hr><h2 id="三、电路设计">三、电路设计</h2><h3 id="3-1-系统硬件组成">3.1 系统硬件组成</h3><p>本系统主要由以下硬件模块组成：</p><h4 id="3-1-1-核心控制模块">3.1.1 核心控制模块</h4><ul><li><strong>芯片</strong>：STC89C52RC单片机</li><li><strong>晶振</strong>：12MHz石英晶振</li><li><strong>复位电路</strong>：上电复位电路（RC复位）</li><li><strong>电源</strong>：5V直流电源供电</li></ul><h4 id="3-1-2-红外接收模块">3.1.2 红外接收模块</h4><ul><li><strong>接收头</strong>：一体化红外接收头（如HS0038、VS1838等）</li><li><strong>工作频率</strong>：38kHz载波频率</li><li><strong>接口</strong>：数据输出引脚连接到单片机P3.2（INT0）</li></ul><p><strong>红外接收头引脚说明</strong>：</p><table><thead><tr><th>引脚</th><th>功能</th><th>连接</th></tr></thead><tbody><tr><td>OUT</td><td>数据输出</td><td>P3.2（INT0）</td></tr><tr><td>GND</td><td>地</td><td>系统地</td></tr><tr><td>VCC</td><td>电源</td><td>+5V</td></tr></tbody></table><h4 id="3-1-3-数码管显示模块">3.1.3 数码管显示模块</h4><ul><li><strong>显示器</strong>：8位共阴极数码管</li><li><strong>段码控制</strong>：P0口输出段码（A-G和DP）</li><li><strong>位选控制</strong>：使用74HC138译码器进行位选<ul><li>P2.2（LSA）→ 74HC138的A</li><li>P2.3（LSB）→ 74HC138的B</li><li>P2.4（LSC）→ 74HC138的C</li></ul></li></ul><p><strong>74HC138译码器真值表</strong>：</p><table><thead><tr><th>LSC</th><th>LSB</th><th>LSA</th><th>选中位</th></tr></thead><tbody><tr><td>0</td><td>0</td><td>0</td><td>第8位</td></tr><tr><td>0</td><td>0</td><td>1</td><td>第7位</td></tr><tr><td>0</td><td>1</td><td>0</td><td>第6位</td></tr><tr><td>0</td><td>1</td><td>1</td><td>第5位</td></tr><tr><td>1</td><td>0</td><td>0</td><td>第4位</td></tr><tr><td>1</td><td>0</td><td>1</td><td>第3位</td></tr><tr><td>1</td><td>1</td><td>0</td><td>第2位</td></tr><tr><td>1</td><td>1</td><td>1</td><td>第1位</td></tr></tbody></table><h3 id="3-2-电路设计要点">3.2 电路设计要点</h3><h4 id="3-2-1-红外接收电路">3.2.1 红外接收电路</h4><ul><li>红外接收头的输出端接单片机外部中断0（P3.2）</li><li>下降沿触发中断，接收红外信号的起始位</li><li>无需外加上拉电阻（接收头内部已集成）</li></ul><h4 id="3-2-2-数码管驱动电路">3.2.2 数码管驱动电路</h4><ul><li><strong>段码驱动</strong>：P0口直接驱动（或通过ULN2003驱动芯片增强驱动能力）</li><li><strong>位选驱动</strong>：74HC138三线译码器，节省3个I/O口控制8位数码管</li><li><strong>限流电阻</strong>：每个段需串联限流电阻（约220Ω-470Ω）</li></ul><h4 id="3-2-3-电源电路">3.2.3 电源电路</h4><ul><li>5V稳压电源供电</li><li>建议添加去耦电容（0.1μF和10μF）在电源引脚附近</li></ul><h3 id="3-3-引脚分配表">3.3 引脚分配表</h3><table><thead><tr><th>功能</th><th>引脚</th><th>说明</th></tr></thead><tbody><tr><td>红外接收</td><td>P3.2</td><td>外部中断0输入</td></tr><tr><td>数码管段码</td><td>P0.0-P0.7</td><td>段码A-G和DP</td></tr><tr><td>位选A</td><td>P2.2</td><td>74HC138的A输入</td></tr><tr><td>位选B</td><td>P2.3</td><td>74HC138的B输入</td></tr><tr><td>位选C</td><td>P2.4</td><td>74HC138的C输入</td></tr></tbody></table><h3 id="3-4-电路示意图">3.4 电路示意图</h3><p>开发板上红外接收模块电路，如下图所示：</p><p>从上图中可以看出，该电路是独立的，红外接收头的输出管脚接至J11端子上，为了保证红外接收头输出管脚默认为高电平，需外接一个10K上拉电阻，可在上图并没有看到有上拉电阻，在前面介绍最小系统时已知道，单片机I0口都增加了10K上拉电阻。</p><p>由于该模块电路是独立的，所以红外接收头的输出管脚J11端子可以使用任意单片机管脚连接，这里使用单片机的P3.2管脚与红外接收头输出管脚连接。</p><h2 id="四、软件设计">四、软件设计</h2><h3 id="4-1-软件架构">4.1 软件架构</h3><p>系统软件采用分层模块化设计，代码结构清晰，便于维护和扩展。</p><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    graph TD    A[main.c 主程序] --&gt; B[ired模块&lt;br&#x2F;&gt;红外接收]    A --&gt; C[smg模块&lt;br&#x2F;&gt;数码管显示]    A --&gt; D[public模块&lt;br&#x2F;&gt;公共函数]    B --&gt; E[ired_init&lt;br&#x2F;&gt;红外初始化]    B --&gt; F[中断服务函数&lt;br&#x2F;&gt;信号解析]    C --&gt; G[smg_display&lt;br&#x2F;&gt;动态扫描显示]    D --&gt; H[delay_10us&lt;br&#x2F;&gt;微秒延时]    D --&gt; I[delay_ms&lt;br&#x2F;&gt;毫秒延时]    style A fill:#ffcccc    style B fill:#ccffcc    style C fill:#ccccff    style D fill:#ffffcc  </pre></div><h3 id="4-2-程序流程设计">4.2 程序流程设计</h3><h4 id="4-2-1-主程序流程">4.2.1 主程序流程</h4><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    flowchart LR    A([开始]) --&gt; B[红外初始化] --&gt; C[主循环] --&gt; D{按键0-20?}    D --&gt;|是| E[十进制显示] --&gt; F[刷新数码管]    D --&gt;|否| G[十六进制显示] --&gt; F    F --&gt; C  </pre></div><p><strong>主程序设计要点</strong>：</p><ol><li>初始化红外接收模块（配置外部中断0）</li><li>进入主循环，持续检测红外数据</li><li>根据接收到的控制码，映射到对应的按键编号（0-20）</li><li>根据按键编号选择显示模式：<ul><li>0-9：左位空白，右位显示个位</li><li>10-20：左位显示十位，右位显示个位</li><li>其他：显示十六进制编码</li></ul></li><li>调用数码管显示函数更新显示内容</li></ol><h4 id="4-2-2-红外接收流程">4.2.2 红外接收流程</h4><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    flowchart LR    A([中断触发]) --&gt; B[检测引导码] --&gt; C[接收4字节数据] --&gt; D{校验通过?}    D --&gt;|是| E[保存数据]    D --&gt;|否| F[清零数据]    E --&gt; G([返回])    F --&gt; G  </pre></div><p><strong>NEC协议解析要点</strong>：</p><ol><li><strong>引导码识别</strong>：9ms低电平 + 4.5ms高电平</li><li><strong>数据位解码</strong>：<ul><li>每位以0.56ms低电平开始</li><li>数据&quot;0&quot;：0.56ms高电平</li><li>数据&quot;1&quot;：1.68ms高电平</li></ul></li><li><strong>数据格式</strong>：4字节（地址码 + 地址反码 + 控制码 + 控制反码）</li><li><strong>校验机制</strong>：控制码与控制反码互为按位取反，用于验证数据正确性</li></ol><h4 id="4-2-3-数码管显示流程">4.2.3 数码管显示流程</h4><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    flowchart LR    A([smg_display]) --&gt; B[循环8位] --&gt; C[位选控制] --&gt; D[输出段码] --&gt; E[延时] --&gt; F{继续?}    F --&gt;|是| B    F --&gt;|否| G([返回])  </pre></div><p><strong>动态扫描原理</strong>：</p><ul><li>利用人眼视觉暂留效应（&gt;50Hz刷新率）</li><li>依次点亮每一位数码管，快速循环扫描</li><li>每位显示时间约1-2ms，总刷新周期约8-16ms</li></ul><h3 id="4-3-核心代码分析">4.3 核心代码分析</h3><h4 id="4-3-1-按键映射表（main-c）">4.3.1 按键映射表（main.c）</h4><p>本系统将红外遥控器的21个按键映射到0-20的编号：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 红外遥控器从上到下从左到右21个键对应0-20（行优先，每行3个按钮）</span></span><br><span class="line"><span class="keyword">switch</span>(gired_data[<span class="number">2</span>]) &#123;</span><br><span class="line">    <span class="keyword">case</span> <span class="number">0x45</span>: num = <span class="number">0</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第1个</span></span><br><span class="line">    <span class="keyword">case</span> <span class="number">0x46</span>: num = <span class="number">1</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第2个</span></span><br><span class="line">    <span class="keyword">case</span> <span class="number">0x47</span>: num = <span class="number">2</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第3个</span></span><br><span class="line">    <span class="comment">// ... 以此类推</span></span><br><span class="line">    <span class="keyword">case</span> <span class="number">0x4A</span>: num = <span class="number">20</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第3个</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="4-3-2-显示逻辑">4.3.2 显示逻辑</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(num&gt;=<span class="number">0</span> &amp;&amp; num&lt;=<span class="number">20</span>) &#123;</span><br><span class="line">    <span class="comment">// 显示0-20：左位显示十位(0则空白)，右位显示个位</span></span><br><span class="line">    <span class="keyword">if</span>(num&lt;<span class="number">10</span>) &#123;</span><br><span class="line">        ired_buf[<span class="number">0</span>]=<span class="number">0x00</span>;           <span class="comment">// 空白</span></span><br><span class="line">        ired_buf[<span class="number">1</span>]=gsmg_code[num];  <span class="comment">// 个位</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        ired_buf[<span class="number">0</span>]=gsmg_code[num/<span class="number">10</span>]; <span class="comment">// 十位</span></span><br><span class="line">        ired_buf[<span class="number">1</span>]=gsmg_code[num%<span class="number">10</span>]; <span class="comment">// 个位</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 十六进制显示（高4位 + 低4位）</span></span><br><span class="line">    ired_buf[<span class="number">0</span>]=gsmg_code[gired_data[<span class="number">2</span>]/<span class="number">16</span>];</span><br><span class="line">    ired_buf[<span class="number">1</span>]=gsmg_code[gired_data[<span class="number">2</span>]%<span class="number">16</span>];</span><br><span class="line">&#125;</span><br><span class="line">ired_buf[<span class="number">2</span>]=<span class="number">0X76</span>; <span class="comment">// 显示&quot;H&quot;标识</span></span><br></pre></td></tr></table></figure><h3 id="4-4-模块接口设计">4.4 模块接口设计</h3><h4 id="4-4-1-public模块（公共函数）">4.4.1 public模块（公共函数）</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 数据类型定义</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">int</span> u16;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">char</span> u8;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">long</span> u32;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 延时函数</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">delay_10us</span><span class="params">(u16 ten_us)</span>;  <span class="comment">// 10微秒级延时</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">delay_ms</span><span class="params">(u16 ms)</span>;         <span class="comment">// 毫秒级延时</span></span><br></pre></td></tr></table></figure><h4 id="4-4-2-ired模块（红外接收）">4.4.2 ired模块（红外接收）</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 全局变量</span></span><br><span class="line"><span class="keyword">extern</span> u8 gired_data[<span class="number">4</span>];  <span class="comment">// 存储接收到的4字节数据</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数接口</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">ired_init</span><span class="params">(<span class="type">void</span>)</span>;      <span class="comment">// 红外初始化函数</span></span><br></pre></td></tr></table></figure><p><strong>初始化配置</strong>：</p><ul><li>IT0=1：设置外部中断0为下降沿触发</li><li>EX0=1：使能外部中断0</li><li>EA=1：开启全局中断</li></ul><h4 id="4-4-3-smg模块（数码管显示）">4.4.3 smg模块（数码管显示）</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 全局变量</span></span><br><span class="line"><span class="keyword">extern</span> u8 gsmg_code[<span class="number">17</span>];  <span class="comment">// 0-F的段码数组</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数接口</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">smg_display</span><span class="params">(u8 dat[], u8 pos)</span>;</span><br><span class="line"><span class="comment">// 参数：dat-段码数组，pos-起始显示位置(1-8)</span></span><br></pre></td></tr></table></figure><p><strong>段码表（共阴极）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0:0x3f  1:0x06  2:0x5b  3:0x4f  4:0x66</span><br><span class="line">5:0x6d  6:0x7d  7:0x07  8:0x7f  9:0x6f</span><br><span class="line">A:0x77  B:0x7c  C:0x39  D:0x5e  E:0x79  F:0x71</span><br></pre></td></tr></table></figure><h3 id="4-5-具体函数实现">4.5 具体函数实现</h3><h4 id="4-5-1-红外初始化函数">4.5.1 红外初始化函数</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;ired.h&quot;</span></span></span><br><span class="line">u8 gired_data[<span class="number">4</span>];<span class="comment">//存储4个字节接收码（地址码+地址反码+控制码+控制反码）</span></span><br><span class="line"><span class="comment">/*******************************************************************************</span></span><br><span class="line"><span class="comment">* 函 数 名         : ired_init</span></span><br><span class="line"><span class="comment">* 函数功能   : 红外端口初始化函数，外部中断0配置 </span></span><br><span class="line"><span class="comment">* 输    入         : 无</span></span><br><span class="line"><span class="comment">* 输    出         : 无</span></span><br><span class="line"><span class="comment">*******************************************************************************/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">ired_init</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">IT0=<span class="number">1</span>;<span class="comment">//下降沿触发</span></span><br><span class="line">EX0=<span class="number">1</span>;<span class="comment">//打开中断0允许</span></span><br><span class="line">EA=<span class="number">1</span>;<span class="comment">//打开总中断</span></span><br><span class="line">IRED=<span class="number">1</span>;<span class="comment">//初始化端口</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>因为我们使用外部中断 0 来解码红外遥控数据，所以需初始化配置外部中断 0</p><h4 id="4-5-2-红外解码函数">4.5.2 红外解码函数</h4><p>初始化外部中断后，中断就已经开启了，当P32引脚来一个下降沿，就会触发一次中断，在中断内我们可以计算高电平时间，通过高电平时间判断是否进入引导码及数据0和1。具体代码如下：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">ired</span><span class="params">()</span> interrupt 0<span class="comment">//外部中断0服务函数</span></span><br><span class="line">&#123;</span><br><span class="line">u8 ired_high_time=<span class="number">0</span>;</span><br><span class="line">u16 time_cnt=<span class="number">0</span>;</span><br><span class="line">u8 i=<span class="number">0</span>,j=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(IRED==<span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line">time_cnt=<span class="number">1000</span>;</span><br><span class="line"><span class="keyword">while</span>((!IRED)&amp;&amp;(time_cnt))<span class="comment">//等待引导信号9ms低电平结束，若超过10ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">1</span>);<span class="comment">//延时约10us</span></span><br><span class="line">time_cnt--;</span><br><span class="line"><span class="keyword">if</span>(time_cnt==<span class="number">0</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(IRED)<span class="comment">//引导信号9ms低电平已过，进入4.5ms高电平</span></span><br><span class="line">&#123;</span><br><span class="line">time_cnt=<span class="number">500</span>;</span><br><span class="line"><span class="keyword">while</span>(IRED&amp;&amp;time_cnt)<span class="comment">//等待引导信号4.5ms高电平结束，若超过5ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">1</span>);</span><br><span class="line">time_cnt--;</span><br><span class="line"><span class="keyword">if</span>(time_cnt==<span class="number">0</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;<span class="number">4</span>;i++)<span class="comment">//循环4次，读取4个字节数据</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(j=<span class="number">0</span>;j&lt;<span class="number">8</span>;j++)<span class="comment">//循环8次读取每位数据即一个字节</span></span><br><span class="line">&#123;</span><br><span class="line">time_cnt=<span class="number">600</span>;</span><br><span class="line"><span class="keyword">while</span>((IRED==<span class="number">0</span>)&amp;&amp;time_cnt)<span class="comment">//等待数据1或0前面的0.56ms结束，若超过6ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">1</span>);</span><br><span class="line">time_cnt--;</span><br><span class="line"><span class="keyword">if</span>(time_cnt==<span class="number">0</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">time_cnt=<span class="number">20</span>;</span><br><span class="line"><span class="keyword">while</span>(IRED)<span class="comment">//等待数据1或0后面的高电平结束，若超过2ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">10</span>);<span class="comment">//约0.1ms</span></span><br><span class="line">ired_high_time++;</span><br><span class="line"><span class="keyword">if</span>(ired_high_time&gt;<span class="number">20</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">gired_data[i]&gt;&gt;=<span class="number">1</span>;<span class="comment">//先读取的为低位，然后是高位</span></span><br><span class="line"><span class="keyword">if</span>(ired_high_time&gt;=<span class="number">8</span>)<span class="comment">//如果高电平时间大于0.8ms，数据则为1，否则为0</span></span><br><span class="line">gired_data[i]|=<span class="number">0x80</span>;</span><br><span class="line">ired_high_time=<span class="number">0</span>;<span class="comment">//重新清零，等待下一次计算时间</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(gired_data[<span class="number">2</span>]!=~gired_data[<span class="number">3</span>])<span class="comment">//校验控制码与反码，错误则返回</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;<span class="number">4</span>;i++)</span><br><span class="line">gired_data[i]=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>进入中断函数，表示以来下降沿，然后判断管脚是否为低电平，如果为低电平则首先判断引导信号，根据前面NEC协议可知，引导信号有9ms的低电平和4.5ms的高电平，因此通过time_cnt赋值1000，然后在while循环内判断，time_cnt每递减一次约10us，1000次则为10ms，在解码时，这个时间要适当放宽一点范围，因为不同传感器性能会有差异，所以此处以10ms的低电平为界限，如果超过10ms则强制退出，防止系统死机。判断完引导信号的低电平，接着判断高电平，实现方法一样。当引导信号判断完成后进入地址码、地址反码、控制码及控制反码共4个字节的数据判断，也就是数据0和1的判断，实现方法也是和前面判断引导信号一样，这里使用到了嵌套循环，外层循环次数是4，表示读取4个字节，内层循环次数是8，表示读取每个字节的8位。注意，红外遥控解码数据是从低位开始，最后是高位。最后将读取的4个字节数据存储在全局变量数组gired_data中，外部可直接使用这四个字节。</p><h4 id="4-5-3-主函数">4.5.3 主函数</h4><p>打开main.c文件，代码如下：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**************************************************************************************  </span></span><br><span class="line"><span class="comment">***************************************************************************************/</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;public.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;smg.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;ired.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*******************************************************************************</span></span><br><span class="line"><span class="comment">* 函 数 名       : main</span></span><br><span class="line"><span class="comment">* 函数功能 : 主函数</span></span><br><span class="line"><span class="comment">* 输    入       : 无</span></span><br><span class="line"><span class="comment">* 输    出     : 无</span></span><br><span class="line"><span class="comment">*******************************************************************************/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">u8 ired_buf[<span class="number">3</span>];</span><br><span class="line"></span><br><span class="line">ired_init();<span class="comment">//红外初始化</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 红外遥控器从上到下从左到右21个键对应0-20（行优先，每行3个按钮）</span></span><br><span class="line"><span class="type">int</span> num = <span class="number">-1</span>;</span><br><span class="line"><span class="keyword">switch</span>(gired_data[<span class="number">2</span>])</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">case</span> <span class="number">0x45</span>: num = <span class="number">0</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x46</span>: num = <span class="number">1</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x47</span>: num = <span class="number">2</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x44</span>: num = <span class="number">3</span>; <span class="keyword">break</span>;  <span class="comment">// 第2行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x40</span>: num = <span class="number">4</span>; <span class="keyword">break</span>;  <span class="comment">// 第2行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x43</span>: num = <span class="number">5</span>; <span class="keyword">break</span>;  <span class="comment">// 第2行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x07</span>: num = <span class="number">6</span>; <span class="keyword">break</span>;  <span class="comment">// 第3行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x15</span>: num = <span class="number">7</span>; <span class="keyword">break</span>;  <span class="comment">// 第3行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x09</span>: num = <span class="number">8</span>; <span class="keyword">break</span>;  <span class="comment">// 第3行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x16</span>: num = <span class="number">9</span>; <span class="keyword">break</span>;  <span class="comment">// 第4行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x19</span>: num = <span class="number">10</span>; <span class="keyword">break</span>; <span class="comment">// 第4行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x0D</span>: num = <span class="number">11</span>; <span class="keyword">break</span>; <span class="comment">// 第4行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x0C</span>: num = <span class="number">12</span>; <span class="keyword">break</span>; <span class="comment">// 第5行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x18</span>: num = <span class="number">13</span>; <span class="keyword">break</span>; <span class="comment">// 第5行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x5E</span>: num = <span class="number">14</span>; <span class="keyword">break</span>; <span class="comment">// 第5行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x08</span>: num = <span class="number">15</span>; <span class="keyword">break</span>; <span class="comment">// 第6行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x1C</span>: num = <span class="number">16</span>; <span class="keyword">break</span>; <span class="comment">// 第6行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x5A</span>: num = <span class="number">17</span>; <span class="keyword">break</span>; <span class="comment">// 第6行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x42</span>: num = <span class="number">18</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x52</span>: num = <span class="number">19</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x4A</span>: num = <span class="number">20</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第3个</span></span><br><span class="line"><span class="keyword">default</span>: num = <span class="number">-1</span>; <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(num&gt;=<span class="number">0</span> &amp;&amp; num&lt;=<span class="number">20</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 显示0-20：左位显示十位(0则空白)，右位显示个位</span></span><br><span class="line"><span class="keyword">if</span>(num&lt;<span class="number">10</span>)</span><br><span class="line">&#123;</span><br><span class="line">ired_buf[<span class="number">0</span>]=<span class="number">0x00</span>; <span class="comment">// 空白</span></span><br><span class="line">ired_buf[<span class="number">1</span>]=gsmg_code[num];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">ired_buf[<span class="number">0</span>]=gsmg_code[num/<span class="number">10</span>]; <span class="comment">// 十位</span></span><br><span class="line">ired_buf[<span class="number">1</span>]=gsmg_code[num%<span class="number">10</span>]; <span class="comment">// 个位</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 保持原来的十六进制显示（高 4 位 + 低 4 位）</span></span><br><span class="line">ired_buf[<span class="number">0</span>]=gsmg_code[gired_data[<span class="number">2</span>]/<span class="number">16</span>];</span><br><span class="line">ired_buf[<span class="number">1</span>]=gsmg_code[gired_data[<span class="number">2</span>]%<span class="number">16</span>];</span><br><span class="line">&#125;</span><br><span class="line">ired_buf[<span class="number">2</span>]=<span class="number">0X76</span>;<span class="comment">//显示H的段码</span></span><br><span class="line">smg_display(ired_buf,<span class="number">6</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="4-5-时序关键点">4.5 时序关键点</h3><h4 id="4-5-1-红外信号时序参数">4.5.1 红外信号时序参数</h4><table><thead><tr><th>参数</th><th>时间</th><th>检测阈值</th></tr></thead><tbody><tr><td>引导码低电平</td><td>9ms</td><td>10ms超时</td></tr><tr><td>引导码高电平</td><td>4.5ms</td><td>5ms超时</td></tr><tr><td>数据位低电平</td><td>0.56ms</td><td>6ms超时</td></tr><tr><td>数据&quot;0&quot;高电平</td><td>0.56ms</td><td>&lt;0.8ms</td></tr><tr><td>数据&quot;1&quot;高电平</td><td>1.68ms</td><td>≥0.8ms</td></tr></tbody></table><h4 id="4-5-2-延时函数精度">4.5.2 延时函数精度</h4><p>基于12MHz晶振（1个机器周期=1μs）：</p><ul><li><code>delay_10us(1)</code>：约10μs</li><li><code>delay_ms(1)</code>：约1ms</li></ul><h3 id="4-6-软件特色">4.6 软件特色</h3><ol><li><strong>健壮的超时机制</strong>：每个等待阶段都有超时保护，防止程序死循环</li><li><strong>数据校验</strong>：通过反码校验确保接收数据的正确性</li><li><strong>位操作高效</strong>：使用位移和位或运算，提高数据处理效率</li><li><strong>模块化封装</strong>：各功能模块独立，接口清晰，便于移植和复用</li></ol><hr><h2 id="五、完整开源代码">五、完整开源代码</h2><p>main.c文件</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**************************************************************************************  </span></span><br><span class="line"><span class="comment">***************************************************************************************/</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;public.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;smg.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;ired.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*******************************************************************************</span></span><br><span class="line"><span class="comment">* 函 数 名       : main</span></span><br><span class="line"><span class="comment">* 函数功能 : 主函数</span></span><br><span class="line"><span class="comment">* 输    入       : 无</span></span><br><span class="line"><span class="comment">* 输    出     : 无</span></span><br><span class="line"><span class="comment">*******************************************************************************/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">u8 ired_buf[<span class="number">3</span>];</span><br><span class="line"></span><br><span class="line">ired_init();<span class="comment">//红外初始化</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(<span class="number">1</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 红外遥控器从上到下从左到右21个键对应0-20（行优先，每行3个按钮）</span></span><br><span class="line"><span class="type">int</span> num = <span class="number">-1</span>;</span><br><span class="line"><span class="keyword">switch</span>(gired_data[<span class="number">2</span>])</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">case</span> <span class="number">0x45</span>: num = <span class="number">0</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x46</span>: num = <span class="number">1</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x47</span>: num = <span class="number">2</span>; <span class="keyword">break</span>;  <span class="comment">// 第1行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x44</span>: num = <span class="number">3</span>; <span class="keyword">break</span>;  <span class="comment">// 第2行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x40</span>: num = <span class="number">4</span>; <span class="keyword">break</span>;  <span class="comment">// 第2行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x43</span>: num = <span class="number">5</span>; <span class="keyword">break</span>;  <span class="comment">// 第2行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x07</span>: num = <span class="number">6</span>; <span class="keyword">break</span>;  <span class="comment">// 第3行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x15</span>: num = <span class="number">7</span>; <span class="keyword">break</span>;  <span class="comment">// 第3行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x09</span>: num = <span class="number">8</span>; <span class="keyword">break</span>;  <span class="comment">// 第3行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x16</span>: num = <span class="number">9</span>; <span class="keyword">break</span>;  <span class="comment">// 第4行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x19</span>: num = <span class="number">10</span>; <span class="keyword">break</span>; <span class="comment">// 第4行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x0D</span>: num = <span class="number">11</span>; <span class="keyword">break</span>; <span class="comment">// 第4行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x0C</span>: num = <span class="number">12</span>; <span class="keyword">break</span>; <span class="comment">// 第5行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x18</span>: num = <span class="number">13</span>; <span class="keyword">break</span>; <span class="comment">// 第5行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x5E</span>: num = <span class="number">14</span>; <span class="keyword">break</span>; <span class="comment">// 第5行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x08</span>: num = <span class="number">15</span>; <span class="keyword">break</span>; <span class="comment">// 第6行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x1C</span>: num = <span class="number">16</span>; <span class="keyword">break</span>; <span class="comment">// 第6行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x5A</span>: num = <span class="number">17</span>; <span class="keyword">break</span>; <span class="comment">// 第6行第3个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x42</span>: num = <span class="number">18</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第1个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x52</span>: num = <span class="number">19</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第2个</span></span><br><span class="line"><span class="keyword">case</span> <span class="number">0x4A</span>: num = <span class="number">20</span>; <span class="keyword">break</span>; <span class="comment">// 第7行第3个</span></span><br><span class="line"><span class="keyword">default</span>: num = <span class="number">-1</span>; <span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(num&gt;=<span class="number">0</span> &amp;&amp; num&lt;=<span class="number">20</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 显示0-20：左位显示十位(0则空白)，右位显示个位</span></span><br><span class="line"><span class="keyword">if</span>(num&lt;<span class="number">10</span>)</span><br><span class="line">&#123;</span><br><span class="line">ired_buf[<span class="number">0</span>]=<span class="number">0x00</span>; <span class="comment">// 空白</span></span><br><span class="line">ired_buf[<span class="number">1</span>]=gsmg_code[num];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">ired_buf[<span class="number">0</span>]=gsmg_code[num/<span class="number">10</span>]; <span class="comment">// 十位</span></span><br><span class="line">ired_buf[<span class="number">1</span>]=gsmg_code[num%<span class="number">10</span>]; <span class="comment">// 个位</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">// 保持原来的十六进制显示（高 4 位 + 低 4 位）</span></span><br><span class="line">ired_buf[<span class="number">0</span>]=gsmg_code[gired_data[<span class="number">2</span>]/<span class="number">16</span>];</span><br><span class="line">ired_buf[<span class="number">1</span>]=gsmg_code[gired_data[<span class="number">2</span>]%<span class="number">16</span>];</span><br><span class="line">&#125;</span><br><span class="line">ired_buf[<span class="number">2</span>]=<span class="number">0X76</span>;<span class="comment">//显示H的段码</span></span><br><span class="line">smg_display(ired_buf,<span class="number">6</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>smg.c</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;smg.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">//共阴极数码管显示0~F的段码数据</span></span><br><span class="line">u8 gsmg_code[<span class="number">17</span>]=&#123;<span class="number">0x3f</span>,<span class="number">0x06</span>,<span class="number">0x5b</span>,<span class="number">0x4f</span>,<span class="number">0x66</span>,<span class="number">0x6d</span>,<span class="number">0x7d</span>,<span class="number">0x07</span>,</span><br><span class="line"><span class="number">0x7f</span>,<span class="number">0x6f</span>,<span class="number">0x77</span>,<span class="number">0x7c</span>,<span class="number">0x39</span>,<span class="number">0x5e</span>,<span class="number">0x79</span>,<span class="number">0x71</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*******************************************************************************</span></span><br><span class="line"><span class="comment">* 函 数 名       : smg_display</span></span><br><span class="line"><span class="comment">* 函数功能 : 动态数码管显示</span></span><br><span class="line"><span class="comment">* 输    入       : dat：要显示的数据</span></span><br><span class="line"><span class="comment">   pos：从左开始第几个位置开始显示，范围1-8</span></span><br><span class="line"><span class="comment">* 输    出     : 无</span></span><br><span class="line"><span class="comment">*******************************************************************************/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">smg_display</span><span class="params">(u8 dat[],u8 pos)</span></span><br><span class="line">&#123;</span><br><span class="line">u8 i=<span class="number">0</span>;</span><br><span class="line">u8 pos_temp=pos<span class="number">-1</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(i=pos_temp;i&lt;<span class="number">8</span>;i++)</span><br><span class="line">&#123;</span><br><span class="line">   <span class="keyword">switch</span>(<span class="number">7</span>-i)<span class="comment">//位选</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">case</span> <span class="number">0</span>: LSC=<span class="number">1</span>;LSB=<span class="number">1</span>;LSA=<span class="number">1</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">1</span>: LSC=<span class="number">1</span>;LSB=<span class="number">1</span>;LSA=<span class="number">0</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">2</span>: LSC=<span class="number">1</span>;LSB=<span class="number">0</span>;LSA=<span class="number">1</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">3</span>: LSC=<span class="number">1</span>;LSB=<span class="number">0</span>;LSA=<span class="number">0</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">4</span>: LSC=<span class="number">0</span>;LSB=<span class="number">1</span>;LSA=<span class="number">1</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">5</span>: LSC=<span class="number">0</span>;LSB=<span class="number">1</span>;LSA=<span class="number">0</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">6</span>: LSC=<span class="number">0</span>;LSB=<span class="number">0</span>;LSA=<span class="number">1</span>;<span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">7</span>: LSC=<span class="number">0</span>;LSB=<span class="number">0</span>;LSA=<span class="number">0</span>;<span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">SMG_A_DP_PORT=dat[i-pos_temp];<span class="comment">//传送段选数据</span></span><br><span class="line">delay_10us(<span class="number">100</span>);<span class="comment">//延时一段时间，等待显示稳定</span></span><br><span class="line">SMG_A_DP_PORT=<span class="number">0x00</span>;<span class="comment">//消音</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>smg.h</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifndef</span> _smg_H</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _smg_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;public.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> SMG_A_DP_PORTP0<span class="comment">//使用宏定义数码管段码口</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">//定义数码管位选信号控制脚</span></span><br><span class="line">sbit LSA=P2^<span class="number">2</span>;</span><br><span class="line">sbit LSB=P2^<span class="number">3</span>;</span><br><span class="line">sbit LSC=P2^<span class="number">4</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">extern</span> u8 gsmg_code[<span class="number">17</span>];</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">smg_display</span><span class="params">(u8 dat[],u8 pos)</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure><p>public.h</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifndef</span> _public_H</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _public_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;reg52.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">int</span> u16;<span class="comment">//对系统默认数据类型进行重定义</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">char</span> u8;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">long</span> u32;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">delay_10us</span><span class="params">(u16 ten_us)</span>;</span><br><span class="line"><span class="type">void</span> <span class="title function_">delay_ms</span><span class="params">(u16 ms)</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>reg52.h</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*--------------------------------------------------------------------------</span></span><br><span class="line"><span class="comment">REG52.H</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">Header file for generic 80C52 and 80C32 microcontroller.</span></span><br><span class="line"><span class="comment">Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.</span></span><br><span class="line"><span class="comment">All rights reserved.</span></span><br><span class="line"><span class="comment">--------------------------------------------------------------------------*/</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">ifndef</span> __REG52_H__</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> __REG52_H__</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*  BYTE Registers  */</span></span><br><span class="line">sfr P0    = <span class="number">0x80</span>;</span><br><span class="line">sfr P1    = <span class="number">0x90</span>;</span><br><span class="line">sfr P2    = <span class="number">0xA0</span>;</span><br><span class="line">sfr P3    = <span class="number">0xB0</span>;</span><br><span class="line">sfr PSW   = <span class="number">0xD0</span>;</span><br><span class="line">sfr ACC   = <span class="number">0xE0</span>;</span><br><span class="line">sfr B     = <span class="number">0xF0</span>;</span><br><span class="line">sfr SP    = <span class="number">0x81</span>;</span><br><span class="line">sfr DPL   = <span class="number">0x82</span>;</span><br><span class="line">sfr DPH   = <span class="number">0x83</span>;</span><br><span class="line">sfr PCON  = <span class="number">0x87</span>;</span><br><span class="line">sfr TCON  = <span class="number">0x88</span>;</span><br><span class="line">sfr TMOD  = <span class="number">0x89</span>;</span><br><span class="line">sfr TL0   = <span class="number">0x8A</span>;</span><br><span class="line">sfr TL1   = <span class="number">0x8B</span>;</span><br><span class="line">sfr TH0   = <span class="number">0x8C</span>;</span><br><span class="line">sfr TH1   = <span class="number">0x8D</span>;</span><br><span class="line">sfr IE    = <span class="number">0xA8</span>;</span><br><span class="line">sfr IP    = <span class="number">0xB8</span>;</span><br><span class="line">sfr SCON  = <span class="number">0x98</span>;</span><br><span class="line">sfr SBUF  = <span class="number">0x99</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*  8052 Extensions  */</span></span><br><span class="line">sfr T2CON  = <span class="number">0xC8</span>;</span><br><span class="line">sfr RCAP2L = <span class="number">0xCA</span>;</span><br><span class="line">sfr RCAP2H = <span class="number">0xCB</span>;</span><br><span class="line">sfr TL2    = <span class="number">0xCC</span>;</span><br><span class="line">sfr TH2    = <span class="number">0xCD</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*  BIT Registers  */</span></span><br><span class="line"><span class="comment">/*  PSW  */</span></span><br><span class="line">sbit CY    = PSW^<span class="number">7</span>;</span><br><span class="line">sbit AC    = PSW^<span class="number">6</span>;</span><br><span class="line">sbit F0    = PSW^<span class="number">5</span>;</span><br><span class="line">sbit RS1   = PSW^<span class="number">4</span>;</span><br><span class="line">sbit RS0   = PSW^<span class="number">3</span>;</span><br><span class="line">sbit OV    = PSW^<span class="number">2</span>;</span><br><span class="line">sbit P     = PSW^<span class="number">0</span>; <span class="comment">//8052 only</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*  TCON  */</span></span><br><span class="line">sbit TF1   = TCON^<span class="number">7</span>;</span><br><span class="line">sbit TR1   = TCON^<span class="number">6</span>;</span><br><span class="line">sbit TF0   = TCON^<span class="number">5</span>;</span><br><span class="line">sbit TR0   = TCON^<span class="number">4</span>;</span><br><span class="line">sbit IE1   = TCON^<span class="number">3</span>;</span><br><span class="line">sbit IT1   = TCON^<span class="number">2</span>;</span><br><span class="line">sbit IE0   = TCON^<span class="number">1</span>;</span><br><span class="line">sbit IT0   = TCON^<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*  IE  */</span></span><br><span class="line">sbit EA    = IE^<span class="number">7</span>;</span><br><span class="line">sbit ET2   = IE^<span class="number">5</span>; <span class="comment">//8052 only</span></span><br><span class="line">sbit ES    = IE^<span class="number">4</span>;</span><br><span class="line">sbit ET1   = IE^<span class="number">3</span>;</span><br><span class="line">sbit EX1   = IE^<span class="number">2</span>;</span><br><span class="line">sbit ET0   = IE^<span class="number">1</span>;</span><br><span class="line">sbit EX0   = IE^<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*  IP  */</span></span><br><span class="line">sbit PT2   = IP^<span class="number">5</span>;</span><br><span class="line">sbit PS    = IP^<span class="number">4</span>;</span><br><span class="line">sbit PT1   = IP^<span class="number">3</span>;</span><br><span class="line">sbit PX1   = IP^<span class="number">2</span>;</span><br><span class="line">sbit PT0   = IP^<span class="number">1</span>;</span><br><span class="line">sbit PX0   = IP^<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*  P3  */</span></span><br><span class="line">sbit RD    = P3^<span class="number">7</span>;</span><br><span class="line">sbit WR    = P3^<span class="number">6</span>;</span><br><span class="line">sbit T1    = P3^<span class="number">5</span>;</span><br><span class="line">sbit T0    = P3^<span class="number">4</span>;</span><br><span class="line">sbit INT1  = P3^<span class="number">3</span>;</span><br><span class="line">sbit INT0  = P3^<span class="number">2</span>;</span><br><span class="line">sbit TXD   = P3^<span class="number">1</span>;</span><br><span class="line">sbit RXD   = P3^<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*  SCON  */</span></span><br><span class="line">sbit SM0   = SCON^<span class="number">7</span>;</span><br><span class="line">sbit SM1   = SCON^<span class="number">6</span>;</span><br><span class="line">sbit SM2   = SCON^<span class="number">5</span>;</span><br><span class="line">sbit REN   = SCON^<span class="number">4</span>;</span><br><span class="line">sbit TB8   = SCON^<span class="number">3</span>;</span><br><span class="line">sbit RB8   = SCON^<span class="number">2</span>;</span><br><span class="line">sbit TI    = SCON^<span class="number">1</span>;</span><br><span class="line">sbit RI    = SCON^<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*  P1  */</span></span><br><span class="line">sbit T2EX  = P1^<span class="number">1</span>; <span class="comment">// 8052 only</span></span><br><span class="line">sbit T2    = P1^<span class="number">0</span>; <span class="comment">// 8052 only</span></span><br><span class="line">             </span><br><span class="line"><span class="comment">/*  T2CON  */</span></span><br><span class="line">sbit TF2    = T2CON^<span class="number">7</span>;</span><br><span class="line">sbit EXF2   = T2CON^<span class="number">6</span>;</span><br><span class="line">sbit RCLK   = T2CON^<span class="number">5</span>;</span><br><span class="line">sbit TCLK   = T2CON^<span class="number">4</span>;</span><br><span class="line">sbit EXEN2  = T2CON^<span class="number">3</span>;</span><br><span class="line">sbit TR2    = T2CON^<span class="number">2</span>;</span><br><span class="line">sbit C_T2   = T2CON^<span class="number">1</span>;</span><br><span class="line">sbit CP_RL2 = T2CON^<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>ired.c</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;ired.h&quot;</span></span></span><br><span class="line"></span><br><span class="line">u8 gired_data[<span class="number">4</span>];<span class="comment">//存储4个字节接收码（地址码+地址反码+控制码+控制反码）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*******************************************************************************</span></span><br><span class="line"><span class="comment">* 函 数 名         : ired_init</span></span><br><span class="line"><span class="comment">* 函数功能   : 红外端口初始化函数，外部中断0配置 </span></span><br><span class="line"><span class="comment">* 输    入         : 无</span></span><br><span class="line"><span class="comment">* 输    出         : 无</span></span><br><span class="line"><span class="comment">*******************************************************************************/</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">ired_init</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">IT0=<span class="number">1</span>;<span class="comment">//下降沿触发</span></span><br><span class="line">EX0=<span class="number">1</span>;<span class="comment">//打开中断0允许</span></span><br><span class="line">EA=<span class="number">1</span>;<span class="comment">//打开总中断</span></span><br><span class="line">IRED=<span class="number">1</span>;<span class="comment">//初始化端口</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">ired</span><span class="params">()</span> interrupt 0<span class="comment">//外部中断0服务函数</span></span><br><span class="line">&#123;</span><br><span class="line">u8 ired_high_time=<span class="number">0</span>;</span><br><span class="line">u16 time_cnt=<span class="number">0</span>;</span><br><span class="line">u8 i=<span class="number">0</span>,j=<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(IRED==<span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line">time_cnt=<span class="number">1000</span>;</span><br><span class="line"><span class="keyword">while</span>((!IRED)&amp;&amp;(time_cnt))<span class="comment">//等待引导信号9ms低电平结束，若超过10ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">1</span>);<span class="comment">//延时约10us</span></span><br><span class="line">time_cnt--;</span><br><span class="line"><span class="keyword">if</span>(time_cnt==<span class="number">0</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(IRED)<span class="comment">//引导信号9ms低电平已过，进入4.5ms高电平</span></span><br><span class="line">&#123;</span><br><span class="line">time_cnt=<span class="number">500</span>;</span><br><span class="line"><span class="keyword">while</span>(IRED&amp;&amp;time_cnt)<span class="comment">//等待引导信号4.5ms高电平结束，若超过5ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">1</span>);</span><br><span class="line">time_cnt--;</span><br><span class="line"><span class="keyword">if</span>(time_cnt==<span class="number">0</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;<span class="number">4</span>;i++)<span class="comment">//循环4次，读取4个字节数据</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(j=<span class="number">0</span>;j&lt;<span class="number">8</span>;j++)<span class="comment">//循环8次读取每位数据即一个字节</span></span><br><span class="line">&#123;</span><br><span class="line">time_cnt=<span class="number">600</span>;</span><br><span class="line"><span class="keyword">while</span>((IRED==<span class="number">0</span>)&amp;&amp;time_cnt)<span class="comment">//等待数据1或0前面的0.56ms结束，若超过6ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">1</span>);</span><br><span class="line">time_cnt--;</span><br><span class="line"><span class="keyword">if</span>(time_cnt==<span class="number">0</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">time_cnt=<span class="number">20</span>;</span><br><span class="line"><span class="keyword">while</span>(IRED)<span class="comment">//等待数据1或0后面的高电平结束，若超过2ms强制退出</span></span><br><span class="line">&#123;</span><br><span class="line">delay_10us(<span class="number">10</span>);<span class="comment">//约0.1ms</span></span><br><span class="line">ired_high_time++;</span><br><span class="line"><span class="keyword">if</span>(ired_high_time&gt;<span class="number">20</span>)<span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">gired_data[i]&gt;&gt;=<span class="number">1</span>;<span class="comment">//先读取的为低位，然后是高位</span></span><br><span class="line"><span class="keyword">if</span>(ired_high_time&gt;=<span class="number">8</span>)<span class="comment">//如果高电平时间大于0.8ms，数据则为1，否则为0</span></span><br><span class="line">gired_data[i]|=<span class="number">0x80</span>;</span><br><span class="line">ired_high_time=<span class="number">0</span>;<span class="comment">//重新清零，等待下一次计算时间</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(gired_data[<span class="number">2</span>]!=~gired_data[<span class="number">3</span>])<span class="comment">//校验控制码与反码，错误则返回</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;<span class="number">4</span>;i++)</span><br><span class="line">gired_data[i]=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>ired.h</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">ifndef</span> _ired_H</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _ired_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;public.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">//管脚定义</span></span><br><span class="line">sbit IRED=P3^<span class="number">2</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//声明变量</span></span><br><span class="line"><span class="keyword">extern</span> u8 gired_data[<span class="number">4</span>];</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//函数声明</span></span><br><span class="line"><span class="type">void</span> <span class="title function_">ired_init</span><span class="params">(<span class="type">void</span>)</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">主要用于记录做项目的笔记和体会</summary>
    
    
    
    <category term="CS" scheme="https://lloydkai.cn/categories/CS/"/>
    
    
    <category term="单片机" scheme="https://lloydkai.cn/tags/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    
  </entry>
  
  <entry>
    <title>CS自学路线系列(一)61A</title>
    <link href="https://lloydkai.cn/posts/CSLearning-61A/"/>
    <id>https://lloydkai.cn/posts/CSLearning-61A/</id>
    <published>2025-08-31T14:23:32.000Z</published>
    <updated>2026-04-23T01:46:34.302Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/OiMP6XG7BR1fHIN.jpg" alt></p><h2 id="相关学习的准备">相关学习的准备</h2><blockquote><p>小tip：</p><p>在google浏览器中按Ctrl+Shift+D，保存当前的所有标签页面到文件夹，下次学习的时候就可以直接右键文件夹打开所有标签页。</p></blockquote><p>建议使用pycharm这个IDE，方便终端输入等。</p><h2 id="Welcome-1pp">Welcome_1pp</h2><p>这篇pdf主要介绍课程的实现目标，规章制度和相关资源的使用，可以参考网页中pdf中的链接找到资源下载并学习。</p><h2 id="Discussion-0：Getting-Started">Discussion 0：Getting Started</h2><p>讨论课0：主要是了解一下函数。可以试着做下面的例题</p><p>Imagine you can call only the following three functions:</p><ul><li><code>f(x)</code>: Subtracts one from an integer <code>x</code></li><li><code>g(x)</code>: Doubles an integer <code>x</code></li><li><code>h(x, y)</code>: Concatenates the digits of two different positive integers <code>x</code> and <code>y</code>. For example, <code>h(789, 12)</code> evaluates to <code>78912</code> and <code>h(12, 789)</code> evaluates to <code>12789</code>.</li></ul><p><strong>Definition</strong>: A <em>small expression</em> is a call expression that contains only <code>f</code>, <code>g</code>, <code>h</code>, the number 5, and parentheses. All of these can be repeated. For example, <code>h(g(5), f(f(5)))</code> is a small expression that evaluates to 103.</p><p>What’s the shortest <em>small expression</em> you can find that evaluates to 2024?</p><p>我的答案如下：</p><p>h(g(g(5)) ,g(g(g(f(f(5))))))</p><h2 id="Lab-0：Getting-Started">Lab 0：Getting Started</h2><h3 id="Setup">Setup</h3><p>教学生安装python并查看Python,以及终端的基础使用，讲得特别详细，而且紧跟Python版本，<u>不像国内的ppt老20年起步，而且不会给如此详细的教学和文档资料</u>.</p><p>目前我使用的是pycharm，也比较推荐使用这种集成的IDE，这样就不需要为了某个功能到处安装插件。</p><p>另外一个扩展阅读：<a href="https://cs61a.org/articles/unix/">https://cs61a.org/articles/unix/</a> 是有关unix和终端的</p><h3 id="Assignment">Assignment</h3><p><a href="https://cs61a.org/lab/lab00/#1-what-would-python-do-wwpd">网站链接</a></p><blockquote><p>以后这些外文资料就用google打开并随时保存在浏览器中的&quot;阅读清单&quot;中</p></blockquote><ol><li>通过命令行打开老师发的zip文档。注意里面的代码不要用</li></ol><p><strong>重点部分</strong></p><blockquote><p>以后的作业基本上都是用ok这个平台，首先用1代码测试是否能使用ok，然后根据作业中的命令测试</p></blockquote><ol><li>用终端进入lab00文件夹，也就是<code>ls</code>时需要有<code>ok</code>这个文件，注意因为我使用的是window，所以老师<strong>命令行中的所有python3都改为python</strong>。</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python ok</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2025/08/31/f2plhACLingT6yX.png" alt></p><p><strong>退出可以用ctrl+z+enter 快捷键</strong>或者输入<code>exit()</code></p><ol start="2"><li>互动式运行py文件</li></ol><p>-i 选项允许以Python命令行互动的形式。你会看到<code>&gt;&gt;&gt;</code> 这样的提示符</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python -i lab00.py</span><br></pre></td></tr></table></figure><ol start="3"><li>测试是否通过所有测试文档(<code>doctests</code>)</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Python -m doctests lab00.py</span><br></pre></td></tr></table></figure><p>其他的命令见链接</p><p>我保存了2024fall版本的课程：在<code>/articles/using-ok.html</code>路径下</p><h2 id="lecture1：Function">lecture1：Function</h2><p>老师讲解了**表达式树(**expression tree)——非常有用，可以解释许多的函数调用问题。</p><p>老师在讲解变量的时候，使用“赋值(assignment)”这个英语单词和<code>bind</code>绑定的英文。</p><h3 id="Environment-Diagrams">Environment Diagrams</h3><p>环境图：So environment diagrams are a way for us to keep track of what’s going on within the Python interpreter when it executes a program that we type in.they are the way in which an interpreter for a programming language keeps track of what names <a href="http://mean.So">mean.So</a> it’s sort of memory that keeps track of the bindings between names and values.</p><p>summary:An environment is a sequence of frames. A frame is a binding between names and values,one of the boxes in the environment diagram.涉及到局部变量和全局变量的使用。</p><p>可以打开此链接<a href="https://pythontutor.com/">https://pythontutor.com/</a> 看到环境图，左边的就是代码(code),右边的就是框架(frame)</p><p>print的副作用(side effect)——推广</p><p>用表达式树的方式解释-函数调用的时候会返回值，无论是否显示在“屏幕”上。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">print</span>(<span class="built_in">print</span>(<span class="number">1</span>),<span class="built_in">print</span>(<span class="number">2</span>))</span><br><span class="line"><span class="comment"># 结果为</span></span><br><span class="line"><span class="comment"># 1</span></span><br><span class="line"><span class="comment"># 2</span></span><br><span class="line"><span class="comment"># None</span></span><br><span class="line"><span class="comment"># None</span></span><br><span class="line"><span class="comment"># 原因：先调用内部的两个print函数，输出为对应的参数，而其函数的side effect 是返回None值，然后作为外层print的参数，所以接连打印两个None</span></span><br></pre></td></tr></table></figure><h3 id="Textbook">Textbook</h3><p>推荐的书籍：<em>Structure and Interpretation of Computer Programs</em> (<a href="http://mitpress.mit.edu/sicp">SICP</a>) 计算机程序的结构与解释</p><p>ch1.1简单介绍了Python及其精神，旨在举一反三，将其思想运用到其他语言的编程中。然后开始教一些基础的Python语法</p><h3 id="Interactive-Sessions">Interactive Sessions</h3><p>交互式会话，Python的交互式会话会以&gt;&gt;&gt; 为开头。开启Python会话的方法是：<br>Type <code>python3</code> at a terminal prompt (Mac/Unix/Linux) or open the Python 3 application in Windows.<br>会话中会记录代码历史，按ctrl+p(previous)/n(next)查看历史，或者是键盘上下键，Ctrl+d退出会话。</p><p>ch1.2 重点介绍了函数，其中涉及到表达式树和<strong>Non-pure functions</strong> ，非纯函数可能产生副作用，从而改变解释器或计算机的状态。<br>比如<code>print(print(1),print(2))</code> 输出结果为<code>1 2 None None</code> 就是因为print函数的返回值是None，在交互式会话中不会出现，但是在编程中容易出现，</p><p>ch1.3 同样重点介绍函数，其中<code>A description of the formal parameters of a function is called the function's signature.</code> 点明了函数签名的本质 <code>Bind the arguments to the names of the function's formal parameters in a new local frame.</code>  指明函数定义的细节，比如<code>from math import sin</code> 就是定义了一个全局“变量”sin，使得名字<code>sin</code> 与math库中的内置函数sin绑定(bind)在一起，所以sin可作为函数执行相关操作，但全局变量sin的任何改变都不影响内置函数的sin，同理，<code>def add(a,b): return a+b</code>是将<strong>名称(name)add与用户定义的函数add绑定</strong>。函数的形式参数也是这样，在函数调用的时候就定义了一个局部变量(比如x),然后将x名称(name)与值绑定，也就是x=2,一旦函数调用完，其本地框架(local frame)也不复存在，所以这就是局部变量不影响全局变量的原理。</p><p>函数的本质</p><blockquote><p>The <em>domain</em> of a function is the set of arguments it can take. The <em>range</em> of a function is the set of values it can return. The <em>intent</em> of a function is the relationship it computes between inputs and output (as well as any side effects it might generate)</p></blockquote><h2 id="Lab-1：Function">Lab 1：Function</h2><blockquote><p>这一部分的作业主要是<strong>用Python写一些相对简单的算法</strong> 只要学过数据结构应该不难做出来</p></blockquote><p>Q1部分</p><ol><li><strong>函数调用顺序</strong>：<code>print(welcome(), cal())</code> 会先调用 <code>welcome()</code> 和 <code>cal()</code> 函数。Python 会从左到右依次计算 <code>welcome()</code> 和 <code>cal()</code> 的返回值。调用 <code>welcome()</code> 时，先执行 <code>print(&quot;Go&quot;)</code>，输出 <code>Go</code>，然后返回字符串 <code>'hello'</code>。调用 <code>cal()</code> 时，先执行 <code>print('Bears')</code>，输出 <code>Bears</code>，然后返回字符串 <code>'world'</code>。</li><li><strong><code>print</code> 函数的最终输出</strong>：<code>welcome()</code> 返回 <code>'hello'</code>，<code>cal()</code> 返回 <code>'world'</code>。<code>print(welcome(), cal())</code> 会将 <code>'hello'</code> 和 <code>'world'</code> 作为参数传递给 <code>print</code>，默认用空格分隔，因此输出 <code>hello world</code>。注意用print不会直接打印出’',需要用转义字符才可以。</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">welcome</span>():</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&quot;Go&quot;</span>)</span><br><span class="line">  <span class="keyword">return</span> <span class="string">&#x27;hello&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">cal</span>():</span><br><span class="line">  <span class="built_in">print</span>(<span class="string">&#x27;Bears&#x27;</span>)</span><br><span class="line">  <span class="keyword">return</span> <span class="string">&#x27;world&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(welcome(),cal())</span><br></pre></td></tr></table></figure><p><strong>Q2部分</strong></p><p>涉及到python的debug和相关编程规范，后续补上相关的问题与回答。</p><h2 id="lecture2：control">lecture2：control</h2><h3 id="Ch1-4">Ch1.4</h3><p>如何设计好的函数，以下是相关的一些建议和准则</p><ul><li>Each function should have exactly one job：每一个函数都应该有一个确定的功能且=</li><li><strong>Don’t repeat yourself</strong> is a central tenet of software engineering(<strong>DRY principle</strong>)：减少重复，一旦出现重复就要考虑函数或者是其他的抽象封装。</li><li>Functions should be defined generally： 定义函数的时候要<strong>笼统</strong>，或者说<strong>普适性</strong> 能写出pow这种能得到任意次幂的函数就不要用sqrt这种只能开方的函数。</li><li>Functions with many arguments can be awkward to call and difficult to read.：<strong>函数的参数不宜过多</strong>，对于很少改变的形式参数可以设置默认值(比如阿伏伽德罗常数、重力加速度等)</li></ul><p>如何写一个好的文档(准确的说是函数的注释)</p><ul><li>Docstrings are conventionally triple quoted：函数的注释要使用三引号</li><li>The first line describes the job of the function in one line. The following lines can describe arguments and clarify the behavior of the function.第一行描述函数的功能，后面几行介绍参数和明确函数的行为。示例代码如下</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">pressure</span>(<span class="params">v, t, n</span>):</span><br><span class="line">        <span class="string">&quot;&quot;&quot;Compute the pressure in pascals of an ideal gas. 计算理想气体的帕斯卡压强 </span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        Applies the ideal gas law: http://en.wikipedia.org/wiki/Ideal_gas_law 应用理想气体定律： 网站链接</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        v -- volume of gas, in cubic meters  v -- 气体体积，立方米</span></span><br><span class="line"><span class="string">        t -- absolute temperature in degrees kelvin t -- 绝对温度，开尔文 </span></span><br><span class="line"><span class="string">        n -- particles of gas  n -- 气体粒子</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        k = <span class="number">1.38e-23</span>  <span class="comment"># Boltzmann&#x27;s constant  玻耳兹曼常数</span></span><br><span class="line">        <span class="keyword">return</span> n * k * t / v</span><br></pre></td></tr></table></figure><ul><li>code is written only once, but often read many times:代码只会写一次，但是会被阅读成千上万次。可以参考Python的文档编写指导学习<a href="https://peps.python.org/pep-0257/">docstring guidelines</a></li></ul><h3 id="Ch1-5">Ch1.5</h3><p>主要讲解：控制语句的语法和函数的写法</p><p>控制语句的目的是决定解释器应该要执行哪一条语句</p><p>函数中的expression用于evaluate value，而return用于将value 返回.大部分函数一般都需要返回值，当然可以没有，比如print</p><p>Python中由header+冒号，并且跟着有缩进的语句就是复合语句，比如 def等</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;header&gt;:</span><br><span class="line">    &lt;statement&gt;</span><br><span class="line">    &lt;statement&gt;</span><br><span class="line">    </span><br><span class="line">&lt;separating header&gt;</span><br></pre></td></tr></table></figure><p><strong>递归本质的揭示</strong></p><p>This definition exposes the essential structure of a recursively defined <em>sequence</em>: a sequence can be decomposed into its first element and the rest of its elements. 用中文的话说就是：一棵树上有多少片叶子，答案是一片叶子，以及剩下的叶子。当你重复这样做的时候，叶子数量也就被你数出来了。</p><p><strong>return语句的作用</strong></p><p>是沟通局部和全局环境的关键语句，通过return语句将其值通过赋值语句存储到全局变量中(或者是某一个局部变量)</p><p><strong>and的短路作用</strong></p><p>如果and左边的值为false,那么and整个的表达式结果就是false，无需判断后面的表达式</p><p><strong>断言assert的作用</strong></p><p>When the expression being asserted evaluates to a true value, executing an assert statement has no effect. When it is a false value, <code>assert</code> causes an error that halts execution</p><p>如果断言为真，对语句没有什么影响；如果断言为假，抛出异常，程序终止，<strong>常用于测试</strong>。</p><p>测试(Doctests)要用专门的文件，在Java中是test.java 在Python中一般建议名字后缀为_test</p><p><strong>测试的书写</strong></p><ol><li><p>第一行描述函数的功能</p></li><li><p>紧跟空行</p></li><li><p>再给几个具体的参数以及期望的结果</p></li><li><p>对于部分函数可以给出交互会话示例，以及如何调用函数</p></li></ol><p>示例</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">sum_naturals</span>(<span class="params">n</span>):</span><br><span class="line">        <span class="string">&quot;&quot;&quot;Return the sum of the first n natural numbers.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">        &gt;&gt;&gt; sum_naturals(10)</span></span><br><span class="line"><span class="string">        55</span></span><br><span class="line"><span class="string">        &gt;&gt;&gt; sum_naturals(100)</span></span><br><span class="line"><span class="string">        5050</span></span><br><span class="line"><span class="string">        &quot;&quot;&quot;</span></span><br><span class="line">        total, k = <span class="number">0</span>, <span class="number">1</span></span><br><span class="line">        <span class="keyword">while</span> k &lt;= n:</span><br><span class="line">            total, k = total + k, k + <span class="number">1</span></span><br><span class="line">        <span class="keyword">return</span> total</span><br></pre></td></tr></table></figure><p>python中有专门的测试库，可以调用 <a href="https://docs.python.org/3/library/doctest.html">参考链接</a></p><p>示例如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> doctest <span class="keyword">import</span> run_docstring_examples</span><br><span class="line"></span><br><span class="line"><span class="comment"># 定义一个自定义函数</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">sum_naturals</span>(<span class="params">n</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;返回从1到n的自然数之和</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &gt;&gt;&gt; sum_naturals(10)</span></span><br><span class="line"><span class="string">    55</span></span><br><span class="line"><span class="string">    &gt;&gt;&gt; sum_naturals(100)</span></span><br><span class="line"><span class="string">    5050</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    total, k = <span class="number">0</span>, <span class="number">1</span></span><br><span class="line">    <span class="keyword">while</span> k &lt;= n:</span><br><span class="line">        total, k = total + k, k + <span class="number">1</span></span><br><span class="line">    <span class="keyword">return</span> total</span><br><span class="line"></span><br><span class="line"><span class="comment"># 开始测试函数</span></span><br><span class="line">run_docstring_examples(sum_naturals,<span class="built_in">globals</span>(),<span class="literal">True</span>)</span><br></pre></td></tr></table></figure><p>得到的结果，这个库函数会根据你在函数中写的测试用例测试，如果函数执行结果和你在测试用例下写的的一样，就返回OK，否则返回错误。所以在写测试用例的时候要写对！！</p><p><strong>以后都需要这样测试，而不是自己随便写一个测试用例</strong>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Finding tests <span class="keyword">in</span> NoName</span><br><span class="line">Trying:</span><br><span class="line">    sum_naturals(10)</span><br><span class="line">Expecting:</span><br><span class="line">    55</span><br><span class="line">ok</span><br><span class="line">Trying:</span><br><span class="line">    sum_naturals(100)</span><br><span class="line">Expecting:</span><br><span class="line">    5050</span><br><span class="line">ok</span><br></pre></td></tr></table></figure><p>在应用函数之前建议先写一些测试用例保证函数的正确性，其中用于测试一个函数的测试被称为unit test(单元测试)</p><h2 id="Disc01">Disc01</h2><p>Q1：Race</p><p>answer：核心就是让tortoise - hare!=0 也就是说，函数循环判断逻辑是有问题的。如果要修改应当是</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">race</span>(<span class="params">x, y</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;The tortoise always walks x feet per minute, while the hare repeatedly</span></span><br><span class="line"><span class="string">    runs y feet per minute for 5 minutes, then rests for 5 minutes. Return how</span></span><br><span class="line"><span class="string">    many minutes pass until the tortoise first catches up to the hare.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">    &gt;&gt;&gt; race(5, 7)  # After 7 minutes, both have gone 35 steps</span></span><br><span class="line"><span class="string">    7</span></span><br><span class="line"><span class="string">    &gt;&gt;&gt; race(2, 4) # After 10 minutes, both have gone 20 steps</span></span><br><span class="line"><span class="string">    10</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">assert</span> y &gt; x <span class="keyword">and</span> y &lt;= <span class="number">2</span> * x, <span class="string">&#x27;the hare must be fast but not too fast&#x27;</span></span><br><span class="line">    tortoise, hare, minutes = <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span></span><br><span class="line">    <span class="keyword">while</span> minutes == <span class="number">0</span> <span class="keyword">or</span> tortoise &gt; =hare: <span class="comment"># 修改的地方</span></span><br><span class="line">        tortoise += x</span><br><span class="line">        <span class="keyword">if</span> minutes % <span class="number">10</span> &lt; <span class="number">5</span>:</span><br><span class="line">            hare += y</span><br><span class="line">        minutes += <span class="number">1</span></span><br><span class="line">    <span class="keyword">return</span> minutes</span><br></pre></td></tr></table></figure><p>Q2：Fizzbuzz</p><p>简单函数，注意判别的顺序即可</p><p><strong>如何解决问题(算法的要求)</strong></p><ol><li>给定一个正确的输入和输出(示例)</li><li>用简单的语句描述如何一步步根据输入得到输出</li><li>弄清你所需要的参数</li><li>使用你所需要的参数</li><li>确定方法是否能适用于原始示例</li><li>确定方法能否适用于其他示例</li></ol><p>Q3：判断是否为质数</p><p>Q4：找出数中只出现一次的数字</p><p>Q5-Q6 是关于Environment Diagrams，也就是局部和全局、return语句相关的知识。需要注意的是函数”赋值“，如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">double</span>(<span class="params">x</span>):</span><br><span class="line">    <span class="keyword">return</span> x * <span class="number">2</span></span><br><span class="line">    </span><br><span class="line"><span class="comment"># double名称指向的是func double(x) [parent=Global]</span></span><br><span class="line">hat = double <span class="comment">#hat也指向的是func double(x) [parent=Global]</span></span><br></pre></td></tr></table></figure><p>不是让hat指向double,而是让hat指向double所指向的函数，本质也就是C的函数指针。</p><p><strong>需要注意的翻译</strong></p><p>assignment statement：赋值语句</p><p>local：在这里要翻译成局部，与之相对的是全局global</p><p>Iteration：迭代</p><h3 id="Ch1-6-Higher-Order-Functions">Ch1.6 Higher-Order Functions</h3><p>概念：操纵函数的函数就叫高阶函数</p><p>新知识：term，类比C++传入函数指针作为参数</p><p><code>term(k)</code> 表示调用函数 <code>term</code> 并传入参数 <code>k</code>，其返回值用于累加。这种设计使得 <code>summation</code> 函数非常通用，可以计算任意形式的累加和，只要传入相应的 <code>term</code> 函数即可</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">summation</span>(<span class="params">n, term</span>):</span><br><span class="line">    total,k = <span class="number">0</span>,<span class="number">1</span></span><br><span class="line">    <span class="keyword">while</span> k&lt;=n:</span><br><span class="line">        total,k = total+term(k),k+<span class="number">1</span></span><br><span class="line">    <span class="keyword">return</span> total</span><br></pre></td></tr></table></figure><p><strong>这种函数的设计非常优雅，将抽象的、重复的逻辑整合为一个高阶函数，在高阶函数中调用”定制“的函数，就可以扩展函数的功能</strong>。</p><p><strong>Nested Functions</strong></p><p>函数嵌套，顾名思义就是在函数里面定义函数并使用</p><p>嵌套函数的特点</p><ul><li>本地函数的名称不会与定义它的函数的外部名称发生冲突，因为本地函数名称将在定义它的当前本地环境中绑定，而不是在全局环境中绑定。</li><li>局部函数可以访问外层函数的环境，因为局部函数的主体是在一个扩展了定义它的评估环境的环境中进行评估的。也就是说函数内部定义的函数可以使用外部函数中的环境，比如变量、参数等等</li></ul><p>词法作用域(<strong>Lexical scope</strong>)：</p><p>核心定义是：<strong>一个变量或符号的可见性（它在哪儿能被访问到）是由它在源代码中的位置决定的，并且在编译时（compile time）就已经确定，而不是在运行时（run time）</strong></p><p>比如将变量定义在函数内部，那么作用域就被定死了。表现为向内访问，向外遮蔽</p><p>利用这些特性，甚至可以返回函数的组合</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">compose1</span>(<span class="params">f, g</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">h</span>(<span class="params">x</span>):</span><br><span class="line">        <span class="keyword">return</span> f(g(x))</span><br><span class="line">    <span class="keyword">return</span> h</span><br></pre></td></tr></table></figure><p><strong>curry: 柯里化</strong></p><p>有些编程语言（如 Haskell）只允许函数接受一个参数，因此程序员必须对所有多参数过程进行 “卷曲”</p><p>示例如下</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">curried_pow</span>(<span class="params">x</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">h</span>(<span class="params">y</span>):</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">pow</span>(x, y)</span><br><span class="line">    <span class="keyword">return</span> h</span><br><span class="line">curried_pow(<span class="number">2</span>)(<span class="number">3</span>)   <span class="comment"># 先将carried_pow返回为h(3) 而x=2已经在pow(2,y)里面，再调入y=3 即可得到8</span></span><br></pre></td></tr></table></figure><p><strong>逆curry化</strong></p><p>可以用逆函数去理解，一个简单的公式为<code>uncurry2(curry2(f))=f</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">uncurry2</span>(<span class="params">g</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;Return a two-argument version of the given curried function.&quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">f</span>(<span class="params">x, y</span>):</span><br><span class="line">        <span class="keyword">return</span> g(x)(y)</span><br><span class="line">    <span class="keyword">return</span> f</span><br><span class="line"></span><br><span class="line"><span class="comment"># 示例</span></span><br><span class="line">uncurry2(curried_pow)(<span class="number">2</span>, <span class="number">5</span>) <span class="comment"># 将uncurry2返回为curried_pow(2)(5),后面的操作就同之前的</span></span><br></pre></td></tr></table></figure><p><strong>匿名函数Lambda(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>λ</mi></mrow><annotation encoding="application/x-tex">\lambda</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span></span></span></span>)</strong></p><p>有趣的知识点：利用英语结构理解Lambda,对于其他编程语言的匿名函数也是一样</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">     lambda            x            :          f(g(x))</span><br><span class="line">&quot;A function that    takes x    and returns     f(g(x))&quot;   </span><br><span class="line"></span><br><span class="line"># 示例</span><br><span class="line">f = composel(lambda x:x*x,lambda y:y+1)</span><br><span class="line">result = f(12)</span><br></pre></td></tr></table></figure><p>建议严格遵循IDE给出的弱警告，有助于养成编写良好代码的习惯。</p><p><strong>装饰器decorator</strong></p><p>和Java的注解有些类似，不过其起到的作用还是高阶函数的那种</p><h2 id="Hw02">Hw02</h2><p>待续…</p>]]></content>
    
    
    <summary type="html">主要用于记录学习伯克利CS61A的笔记和心得体会，旨在打下坚实的Python和计算机知识基础，为后续CS61B和阅读外语技术文档和学习资源做准备。</summary>
    
    
    
    <category term="CS" scheme="https://lloydkai.cn/categories/CS/"/>
    
    
    <category term="CS自学路线" scheme="https://lloydkai.cn/tags/CS%E8%87%AA%E5%AD%A6%E8%B7%AF%E7%BA%BF/"/>
    
    <category term="Python" scheme="https://lloydkai.cn/tags/Python/"/>
    
  </entry>
  
  <entry>
    <title>健康与长寿之路</title>
    <link href="https://lloydkai.cn/posts/road-to-health/"/>
    <id>https://lloydkai.cn/posts/road-to-health/</id>
    <published>2025-07-30T07:25:31.000Z</published>
    <updated>2026-04-23T01:43:52.295Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/06/14/9oPncpgrjCfQ1Mw.png" alt></p><h2 id="前言">前言</h2><blockquote><p>”起初，没有人在意这一场灾难，这不过是一场山火、一次旱灾、一个物种的灭绝、一座城市的消失，直到这场灾难和每个人息息相关。”——《流浪地球》</p></blockquote><p>在重病缠身之前，没有人会意识到自己的生活作息、饮食习惯有什么不合理的地方。作者就是这样的，直到干扰了正常的生活才开始亡羊补牢，这次去了医院我才开始反思自己的作息与饮食，虽然相比大学生比较规律，但是这只不过是五十步笑百步，<strong>亚健康不是真正的健康</strong>，藉此事件，我写下了这篇博客，想要规划自己的饮食和生活。</p><p>目前版本version1.0,alpha版。在后续生活中会不断完善。</p><h2 id="日常篇">日常篇</h2><h3 id="关于睡眠💤">关于睡眠💤</h3><p>如果你是学生党或者职业性工作时间长，我建议<strong>尽可能保证7.5小时的睡眠时间</strong>，比如23.00-6.30，可以适当延长和调整时间，不过一般来说超过11.00就算是熬夜了，建议尽可能在11.00之前睡觉。</p><p>此外，如果有条件的话可以适当午休，一般20-30min比较好，睡多了会影响晚上的睡眠。</p><p>还有一点，如果要喝咖啡的话(一般如果睡眠正常是不需要咖啡的，也不建议含有大量咖啡因的饮料)，推荐下午2点之前喝，否则就会影响晚上的睡眠状态，不过也有人喝了咖啡就容易睡着，毕竟人和人之间的体质不能一概而论，但是有一点是可以确定的——<strong>少喝咖啡</strong>，尤其是互联网行业，经常有喝咖啡过多结石的人。</p><p>如果你是习惯性熬夜，一个好方法是使用类似与<strong>番茄todo</strong>这样的软件，在固定的时间把<strong>手机强制关机</strong>，逼着你早点睡觉；或者是睡前听一听“高等数学”，看一下看不懂的书(比如教材等)，反正就是平常干什么容易困的，你就晚上怎样做。</p><h3 id="关于刷牙与漱口😁">关于刷牙与漱口😁</h3><p>我的规划是，一天两次，早晚刷牙，刷牙的时候用一些含氟的牙膏，主要是为了防止龋齿，参考<a href="https://zhuanlan.zhihu.com/p/277366263">巴氏刷牙法</a>。每次吃完饭就漱下口，主要是去除口腔中多余的残渣。</p><p>至于电动牙刷，这个我不太清楚，没有用过，也许以后尝试一下？如果确实能提高刷牙的质量的话，那也是一笔不错的健康投资。</p><p>牙齿是人体最坚硬的部分，但是只要你持之以恒的吃甜食、不刷牙不漱口，总有一天也会溃于蚁穴的吧(反讽😏)</p><h3 id="关于用耳👂">关于用耳👂</h3><p>作者就在这上面中招了，如果你长期使用入耳式耳机，并且声音开得很大，那就非常容易听力受损，甚至会伴随耳鸣、眩晕等症状。因此建议是，平时没必要就不要戴耳机，耳塞应该问题不大，不过也不要经常戴；同时如果是去到高噪音的环境(尤其是机械老哥和土木老哥)，<strong>一定一定要做好耳朵保护</strong>，临时带上降噪耳机等，不然晚上睡觉都是机床切割，锤头作响的声音，余音绕梁，三晌未绝(😖)。</p><h3 id="关于不良嗜好🚭">关于不良嗜好🚭</h3><p><strong>吸烟</strong>🚬</p><p>一句话概括：吸烟有害健康。有则戒掉，无则加勉。</p><p><strong>喝酒</strong>🍹</p><p>据WHO的一份报道之处，酒精的建议摄入量为零。就我个人而言，酒在口感上不如豆浆一根，营养价值没有豆浆好，甚至比豆浆贵，除了社交价值和炫富价值我想不到喝酒的理由，也不建议喝酒。而且酒的健康影响问题是在西方有先例的，经典起手就是“目前没有足够的证据表明酒有害健康”-“虽然有一定的证据，但是研究不够充分，正确性有待商榷”-“虽然酒有害健康，但是适量的酒有益健康”-“绿色有机无害环保酒”… 诸如此类，不胜枚举。</p><h2 id="饮食篇">饮食篇</h2><h3 id="进食时间🕚">进食时间🕚</h3><p>⭐<strong>8 小时进食窗口的间歇性断食相对来说比较适合大部分人</strong>，如果你是学生党或者是从事职业体能消耗大，可以适当吃一点早餐，不过总体上基本上是<strong>早上 11:30 到晚上 7:30 之间进食，不吃早饭和夜宵</strong>。严格来说禁食主要是依据血糖水平。</p><p>对学生党来说最好早上稍微吃一点东西填饱肚子，毕竟消耗比较大，如果不吃早饭容易低血糖，早上不吃早饭感觉头脑会更清醒，晚上不吃夜宵对睡眠质量也有促进作用。</p><p>至于其他的饮食时间方法，我没有尝试过，主要是专业性太强，实操性比较弱，读者可以自行Google。</p><h3 id="健康的饮食🍚">健康的饮食🍚</h3><p>这里我比较推荐看WHO(世界卫生组织)的饮食规划，然后根据自己的实际情况调整。<a href="https://www.who.int/zh/news-room/fact-sheets/detail/healthy-diet">世界卫生组织健康饮食</a></p><h3 id="吃饭的顺序​​">吃饭的顺序​​</h3><p>先吃蔬菜这类富含纤维素的食物，再吃肉类，最后才是碳水或含糖的食物.因为血糖的剧烈波动是“<strong>万恶之源</strong>”。</p><p>就我观察而言，农村的爷爷奶奶辈就是这样吃的，他们一般上午六七点左右起床，做一些喂鸡、洗衣等轻度劳动，然后到10点左右开始吃第一顿饭，一般也是素菜多余荤菜，然后开始做一些重体力活，比如砍柴和插秧等，在下午四点左右吃第二顿饭，继续干活，一般到晚上67点左右就回家，没有晚饭。这样做的好处是<strong>降低了饮食的频率，同时通过运动降低了血糖的剧烈变化</strong>。所以我见到的大部分在农村长大的孩子，一般身体素质都很不错，很少得病。</p><h3 id="点外卖的原则🍔">点外卖的原则🍔</h3><p>什么？你问我为什么不自己做饭？<s>当然是因为自己不会做</s>，其实所有人都知道自己做饭比较健康，但是大部分情况是，一不会做饭，二没有时间做饭，三是做饭1小时，吃饭10min，性价比太低，如果我能够像北欧人那样惬意的生活，不被繁忙的社会氛围所裹挟的话，我当然愿意自己做饭，但很可惜不是。所以，这里列举出我自己认为比较重要的几点，尽可能减少外卖带来的健康影响</p><ol><li>如果点轻食，要注意一下配料内容，比如西兰花，菠菜，羽衣甘蓝，彩椒，豆类，牛油果之类的就比较好。<strong>绝对不吃酱料，一吃酱料全毁了</strong>。</li><li>干净的中式快餐也挺好的，轻食里那么多生菜炒一下可能没几片叶子，吃个炒青菜说不定纤维素还更多些。</li><li>麻辣烫也不错，只要汤底别重口味，水煮蔬菜。</li><li><strong>建议不要点面条、炒饭炒粉之类的</strong>(比如热干面)，前者饱腹感低容易在无意识的情况下摄入过多，后者是碳水量过大而蔬菜等摄入过少。</li><li>尽可能每一顿中都有至少两种以上的蔬菜，比较推荐的是油麦菜、上海青、白菜等家常蔬菜、各种萝卜</li></ol><h3 id="馋人的小零食🍰">馋人的小零食🍰</h3><p><strong>先说结论，建议摄入量是零，要吃也只是非必要不吃</strong>。以下是常见的零食</p><ul><li>小麦制品，饼干，蛋糕烘培等,</li><li>巧克力，果汁,油炸食品，人造奶油，奶茶等</li><li>腌制肉类(一般主要是过年的时候吃的比较多，建议少吃和不吃),各种酱料(包括外卖中的和家里做菜用的)，深度加工，配料表长，保质期长的</li></ul><p>这些零食的特点一般是：要么含碳水量过高，导致前面8小时进餐的努力和锻炼的努力都白费了；要么糖分过高，长期累积最严重的情况下就是“糖尿病”；要么就是含盐量过高，对高血压不好，尤其是那些<strong>有高血压的人，一定要控制日常饮食的含盐量</strong>。</p><p><strong>基本上在超市里看见的所有的零食和饮料都不建议</strong>，也就是说，<strong>非必要不要在三餐以外的时间摄取食物</strong>，这是最理想最健康的情况。</p><p>当然，也不必为自己的自制力差而自责，我们的目的是长久的健康，也就是说，偶尔吃一点没什么(比如一个月一两次)，但是<strong>不能经常偶尔</strong>。</p><h2 id="运动篇🏀">运动篇🏀</h2><p>这里作者给学生党(尤其是考研党)的建议是，<strong>一周3-4次跑步，一次建议跑个2-3公里</strong>，当然我们不追求速度，主要是让身体运动起来。当然你有自己喜欢的运动都可以，这都是好事(by 常凯申)</p><p>作者从2月开始运动的时候，一开始6min跑1200m都很费劲，但是后面持之以恒练习之后，就能做到1200跑进5min20s,这个成绩不算耀眼，但是会给你变强的感觉，这种自信心的增强和身体的改善是运动独有的，强烈建议读者养成一个持久锻炼的习惯，一旦形成，带来的就是无穷的power!!</p><p>此外，需要注意的是建议睡前2小时不要锻炼，容易睡不着(作者亲测)。</p><h2 id="参考文献">参考文献</h2><ul><li><a href="https://zhuanlan.zhihu.com/p/675470252">养生博主的23年总结</a></li><li><a href="https://github.com/zijie0/HumanSystemOptimization">健康学习到150岁 - 人体系统调优不完全指南</a></li><li><a href="https://www.who.int/zh/news-room/fact-sheets/detail/healthy-diet">世界卫生组织健康饮食</a></li></ul>]]></content>
    
    
    <summary type="html">旨在为自己的日常生活制定合理的饮食和作息规划，最终维护身体健康</summary>
    
    
    
    <category term="life" scheme="https://lloydkai.cn/categories/life/"/>
    
    
    <category term="life" scheme="https://lloydkai.cn/tags/life/"/>
    
  </entry>
  
  <entry>
    <title>《高质量C&amp;&amp;C++》个人读书心得</title>
    <link href="https://lloydkai.cn/posts/cprimeplus-note/"/>
    <id>https://lloydkai.cn/posts/cprimeplus-note/</id>
    <published>2025-05-31T03:35:45.000Z</published>
    <updated>2026-04-23T02:21:37.638Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/22/JIZCAPigNfBVQTa.jpg" alt></p><blockquote><p>本文章会随着编程能力的提高和思维的扩展不断更新,目前是1.1版本</p></blockquote><h1>简介</h1><p>本书以高质量编写C/C++代码为主题，在代码风格等方面列举了常见的规则和示例，旨在帮助读者写出风格统一的、可读性强的、易于维护的代码。</p><h1>代码风格</h1><blockquote><p>什么是优秀的、高质量的代码?</p></blockquote><ul><li>优秀的编程风格</li><li>有出错处理</li><li>算法复杂度分析</li></ul><h2 id="文章结构">文章结构</h2><h3 id="版权与版本的声明">版权与版本的声明</h3><p><strong>版权和版本的声明</strong>:<br>位于<strong>头文件</strong>(.h)和<strong>定义文件</strong>(.cpp或者.c)的开头,主要内容有：</p><ul><li>版权信息.</li><li>文件名称,标识符,摘要.</li><li>当前版本号,作者/修改者,完成日期.</li><li>版本历史信息.</li></ul><p><strong>示例1-1</strong>：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">* Copyright(c)200l,上海贝尔有限公司网络应用事业部</span></span><br><span class="line"><span class="comment">* All rights reserved.</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">* 文件名称：filename.h</span></span><br><span class="line"><span class="comment">* 文件标识：见配置管理计划书</span></span><br><span class="line"><span class="comment">* 摘　要：简要描述本文件的内容</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">* 当前版本：1.1</span></span><br><span class="line"><span class="comment">* 作者：输入作者(或修改者)名字</span></span><br><span class="line"><span class="comment">*完成日期：2001年7月20日</span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">* 取代版本：1.0</span></span><br><span class="line"><span class="comment">＊原作者：输入原作者(或修改者)名字</span></span><br><span class="line"><span class="comment">* 完成日期：2001年5月10日</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><h3 id="头文件的结构">头文件的结构</h3><ul><li>头文件开头处的版权和版本声明(参见示例1-1).</li><li>预处理块.</li><li>函数和类结构声明等.</li></ul><p><strong>规则</strong>;</p><ol><li>&lt;&gt;导入标准库的头文件,“” 导入非标准库的头文件</li><li>头文件只存放<strong>声明</strong>而不放<strong>定义</strong></li></ol><p><strong>示例1-2</strong> 使用ifndef</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//假设头文件名称为graphics.h</span></span><br><span class="line"><span class="comment">//版权和版本声明见示例1-1,此处省略.</span></span><br><span class="line"><span class="meta">#<span class="keyword">ifndef</span> GRAPHICS_H ∥防止graphics.h被重复引用</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> GRAPHICS_H</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;math.h&gt;</span> ∥引用标准库的头文件</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;myheader.h&quot;</span> ∥引用非标准库的头文件</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Functionl</span><span class="params">()</span></span>;<span class="comment">//全局函数声明</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Box</span> <span class="comment">//类结构声明</span></span><br><span class="line">&#123;</span><br><span class="line">    </span><br><span class="line">&#125;;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br></pre></td></tr></table></figure><p>特点：能跨平台,但是编译时间较长,而且一旦宏名重复就会“不知所措“</p><p><strong>示例1-2</strong>  使用#pragma once</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _CRT_SECURE_NO_WARNINGS</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;typeinfo&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sstream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;memory&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;chrono&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;thread&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;Windows.h&gt;</span></span></span><br></pre></td></tr></table></figure><p>特点：编译时间短,但是难以跨平台.</p><h3 id="定义文件的结构">定义文件的结构</h3><ul><li>定义文件开头处的版权和版本声明(参见示例1-1).</li><li>对一些头文件的引用.</li><li>程序的实现体(包括数据和代码).<br>假设定义文件的名称为graphics.cpp,定义文件的结构参见示例1-3.</li></ul><p><strong>示例1-3</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//版权和版本声明见示例1-1,此处省略.</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span>“graphics.h”∥引用头文件</span></span><br><span class="line">……</span><br><span class="line"><span class="comment">//全局函数的实现体</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Functionl</span><span class="params">(…)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">……</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//类成员函数的实现体</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Box::Draw</span><span class="params">(…)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">……</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="目录结构">目录结构</h3><p>如果一个软件的头文件数目比较多(如超过十个),通常应将头文件和定义文件分别保存于不同的目录,以便于维护.例如可将头文件保存于include目录,将定义文件保存于source目录(可以是多级目录).</p><h2 id="程序的版式">程序的版式</h2><h3 id="空行">空行</h3><p><strong>适当留空行保持呼吸感</strong></p><p><strong>规则</strong>:</p><ul><li>在每个类声明之后、每个函数定义结束之后都要加空行.</li><li>在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔.参见示例2-1</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//逻辑连续,不空行</span></span><br><span class="line"><span class="type">int</span> ii = <span class="number">3</span>;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;typeid(int)=&quot;</span> &lt;&lt; <span class="built_in">typeid</span>(<span class="type">int</span>).<span class="built_in">name</span>() &lt;&lt; endl,</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;typeid(ii)=&quot;</span> &lt;&lt; <span class="built_in">typeid</span>(ii).<span class="built_in">name</span>() &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义函数,前后逻辑不相连,空行</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">print</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">power</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="代码行">代码行</h3><p><strong>规则</strong></p><ul><li><strong>一行代码只做一件事情</strong>,如只定义一个变量,或只写一条语句.这样的代码容易阅读,并且方便于写注释.</li><li>if、for、while、do等语句自占一行,执行语句不得紧跟其后.<strong>不论执行语句有多少都要加{}</strong>.这样可以防止书写失误.</li><li>尽可能<strong>定义变量的同时初始化该变量</strong>.</li></ul><blockquote><p><strong>总而言之一句话,不要一行就写完</strong></p></blockquote><p><strong>示例2-2</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在定义变量的同时初始化变量</span></span><br><span class="line"><span class="type">int</span> width = <span class="number">10</span>;<span class="comment">//宽度</span></span><br><span class="line"><span class="type">int</span> height = <span class="number">20</span>;<span class="comment">//高度</span></span><br><span class="line"><span class="type">int</span> depth = <span class="number">30</span>;<span class="comment">//深度</span></span><br><span class="line"><span class="comment">//不要写成int width,height,depth;</span></span><br><span class="line"></span><br><span class="line">x  = a +b;</span><br><span class="line">y = c + d;</span><br><span class="line">z = e - f;</span><br><span class="line"><span class="comment">//不要一行就写完</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (width &lt; height)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">dosomething</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//不要写成 if() dosomething</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (initialization;condition;update)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">dosomething</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//空行</span></span><br><span class="line"><span class="built_in">other</span>();</span><br></pre></td></tr></table></figure><h3 id="代码行内的空格">代码行内的空格</h3><ul><li>关键字之后要留空格.象const、virtual、inline、case等关键字之后至少要留一个空格(不留空格一般会报错),否则无法辨析关键字.<strong>象if、for、while等关键字之后应留一个空格</strong>再跟左括号‘(’,以突出关键字.</li><li><strong>函数名之后不要留空格</strong></li><li>‘(’向后紧跟,<strong>‘)’、‘,’、’‘;’向前紧跟</strong>,紧跟处不留空格.</li><li>‘,’之后要留空格,如Function(x,y,z).如果‘;’不是一行的结束符号,其后要留空格,如for(initialization; condition; update).</li><li>赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=”“&gt;=”、“&lt;=”、“+”、“*”、“%”、“&amp;&amp;”、“‖”、“&lt;”,“Λ”等二元操作符的前后应当加空格.(在VS等编译器会自动格式化,但是也要养成良好的习惯)</li><li>一元操作符如“”！“~”、“++”、“–”、“&amp;”(地址运算符)等前后不加空格.</li><li>象“[]”、“.”、“-&gt;”这类操作符前后不加空格.</li><li>对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for(i=0;i&lt;10;i++)和if(a&lt;=b)&amp;&amp;(c&lt;=d)</li></ul><p>也就是说：<strong>在有大量操作符或者是关键字的情况下留空格避免过于紧凑</strong>.对于需要紧凑的符号就不要留空(比如&amp;,this等)</p><p><strong>示例</strong> 以下皆为优良代码风格</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">Funcl</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y,<span class="type">int</span> z)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (year &gt;= <span class="number">2000</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>((a&gt;=b) &amp;&amp; (c&lt;=d))</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>; i&lt;<span class="number">10</span>; i++)</span><br><span class="line"></span><br><span class="line">x = a &lt; b ? a : b;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> *x = &amp;y;</span><br><span class="line"></span><br><span class="line">array[<span class="number">5</span>] = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">a.<span class="built_in">Function</span>();</span><br></pre></td></tr></table></figure><h3 id="对齐">对齐</h3><p><strong>规则简单来说就是{}单独占一行并且同一级的要对齐</strong>.</p><p><strong>示例</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">func</span><span class="params">(string name)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10</span>; i++)</span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; name &lt;&lt; <span class="string">&quot;will make America great again&quot;</span>&lt;&lt; i &lt;&lt; endl;</span><br><span class="line"><span class="built_in">Sleep</span>(<span class="number">1000</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="长行拆分">长行拆分</h3><ul><li>一行最多70-80字</li><li>拆分时将操作符放在首位,要缩进排版</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> ((very_longer_variablel &gt;very_longer_variablel2)</span><br><span class="line">&amp;&amp;(very_longer_variable3 &lt;very_longer_variablel4)</span><br><span class="line">&amp;(very_longer_variable5 &lt;very_longer_variablel6))</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">dosomething</span>(first_name,</span><br><span class="line">    last_name);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="修饰符的位置">修饰符的位置</h3><p>主要是解决多个变量定义时的歧义问题</p><p>规则:*与&amp;紧靠变量名</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">char</span> *name;</span><br><span class="line"><span class="type">int</span> *x,y;<span class="comment">//y不会误解为指针</span></span><br><span class="line"><span class="type">int</span>* x,y;<span class="comment">//y有可能被误解为指针.</span></span><br></pre></td></tr></table></figure><h3 id="注释">注释</h3><p><strong>规则</strong></p><ul><li>一行用//,多行用/ * * /</li><li>注释不是文档,需要的时候才加上</li><li>边写代码边注释,注意更新</li><li>注释要写在所解释的代码的上方或者右方</li><li>较长的代码要在结尾处指明是谁的结束.</li></ul><p><strong>示例</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>()</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">while</span> ()</span><br><span class="line">&#125;<span class="comment">//end of while</span></span><br><span class="line"></span><br><span class="line">&#125;<span class="comment">//end of if</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">* 函数介绍：</span></span><br><span class="line"><span class="comment">* 输入参数：</span></span><br><span class="line"><span class="comment">* 输出参数：</span></span><br><span class="line"><span class="comment">* 返回值</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><h3 id="类的版式">类的版式</h3><p>类的版式主要有关心结构的“以数据为中心”风格和“以行为为中心“风格,这里提倡**“以行为为中心“风格**,毕竟在大部分情况下我们只关心怎样使用,有什么功能,而不会在乎里面是什么.</p><p>一句话：<strong>将public类型的函数放在前面,将private的数据放在后面</strong>.</p><p><strong>示例</strong>：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Funcl</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Func2</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"><span class="type">int</span> i,j:</span><br><span class="line"><span class="type">float</span> x,y;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="命名">命名</h2><p>在实际工作中以<strong>企业的开发手册</strong>为主</p><p><strong>规则</strong></p><ul><li>不要用拼音,不用写完整英文翻译,也不要用中式英语命名</li><li>统一命名风格,要么驼峰命名法,要么匈牙利命名法,不要混着用.这里采用驼峰命名法<ul><li>扩展：驼峰命名法:</li><li><strong>变量</strong>一般用<strong>小驼峰法</strong>标识.驼峰法的意思是：除第一个单词之外,其他单词首字母大写</li><li>大驼峰法把<strong>第一个单词的首字母也大写</strong>了.常用于类名,函数名,属性,命名空间</li></ul></li><li>少用易混淆的标识符,比如x与X,o与0</li><li>变量的名字(&quot;名词“或者”形容词+名词“)</li><li>全局函数的名字(“动词“或者&quot;动词+名词”),类中的函数命名(“动词”),因为&quot;自带&quot;名词.</li><li>可以用反义词组表示具有相反意义的变量或者函数(如set与get)</li><li>避免数字编号;比如num1;</li></ul><p><strong>Windows命名规则</strong></p><ul><li>常量全大写,下划线分割单词.如int  MAX_NUM = 100;</li><li>静态变量加s_前缀,全局变量加g_前缀,类成员加m_前缀  如int static s_num = 100;</li><li>对于不同库的变量可以添加反映库特性的前缀,如openGL,用gl_做前缀</li></ul><h3 id="表达式和基本语句">表达式和基本语句</h3><h3 id="运算符的优先级-复合表达式">运算符的优先级 &amp;&amp; 复合表达式</h3><p><strong>规则</strong></p><ul><li>适当用括号表示运算顺序</li><li>不要写复杂、多用途的表达式,除非你是出面试题的考官.比如<code>d = (a=b+c++)+r;</code></li></ul><h3 id="if语句">if语句</h3><p>规则</p><ul><li>不要将布尔值或者是0,1值直接进行比较. 比如能写<code>if(flag)</code> 就不要写 <code>if(flag == true)</code> 写<code>if(value == 0)</code> 就不要写<code>if(value == false)</code> 虽然false和0值相等,但是类型不同</li><li>浮点数不要用<code>==</code> <code>!=</code> 比较.因为浮点数精度问题</li><li>指针一般和NULL比较,或者和nullptr(C++11特性)比较</li><li>建议比较的时候将确定的数放在 == 之前,防止错写成=而无法发觉.</li></ul><p><strong>示例</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">10</span>;</span><br><span class="line"><span class="keyword">if</span> (<span class="number">10</span> == a)</span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;a=10&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//如果你写成=会自动给你报错,防止出事</span></span><br><span class="line"><span class="keyword">if</span>(<span class="number">10</span> = a)</span><br><span class="line">&#123;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="循环语句的效率">循环语句的效率</h3><p>规则</p><ul><li>建议将最长的循环放在内层,减少CPU跨切循环层的次数</li><li>逻辑判断最好在循环外面</li></ul><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//不用for循环里面每次都判断条件,提高了效率</span></span><br><span class="line"><span class="keyword">if</span> (condition)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">0</span>;i&lt;N;i++)</span><br><span class="line"><span class="built_in">DoSomething</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (i=<span class="number">0</span>;i&lt;N;i++)</span><br><span class="line"><span class="built_in">DoOtherthing</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="for循环与switch多分支">for循环与switch多分支</h3><p>规则</p><ul><li>不要轻易在for里面改变循环变量</li><li>for循环控制变量取值采用前闭后开的方法.能写<code>for (int i = 0;i &lt; 5;i++)</code>  就不要写`for (int i = 0;i &lt;=4;i++)</li><li>每个case都要写break防止case击穿.保留default语句</li></ul><h3 id="goto">goto</h3><ul><li>慎用goto,用的好能跳出重重封锁(比如嵌套循环),用不好就万劫不复</li></ul><h2 id="常量">常量</h2><p>使用常量的好处在于<strong>一劳永逸,见文知意</strong></p><p>规则</p><ul><li>用常量表示多次出现的数字或者字符串</li><li>建议用const代替#define,方便调试.</li><li>公开的常量放在头文件中,不公开的放在定义文件中</li><li>常量之间有关联的用常量代替而不是用数字</li></ul><p><strong>示例</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> MAX 100 <span class="comment">/*C语言的宏常量*/</span></span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAX = <span class="number">100</span>; <span class="comment">//C++语言的const常量</span></span><br><span class="line"><span class="type">const</span> <span class="type">float</span> PI = <span class="number">3.14159</span>; <span class="comment">//C++语言的const常量</span></span><br><span class="line"><span class="type">const</span> string NAME = <span class="string">&quot;Lloyd&quot;</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> NUN = MAX * <span class="number">10</span>;</span><br></pre></td></tr></table></figure><p><strong>类中设计常量</strong><br>不能直接用const,建议使用<strong>枚举</strong></p><p><strong>示例</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">A</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">enum</span>&#123;SIZE1=<span class="number">100</span>,SIZE2=<span class="number">200</span>&#125;;<span class="comment">//枚举常量</span></span><br><span class="line"><span class="type">int</span> array_fir[SIZE1];</span><br><span class="line"><span class="type">int</span> array_sec[SIZE1];</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="函数设计">函数设计</h2><h3 id="规则">规则</h3><p>形参名</p><ul><li>形参名要写完整不要省,没有就用void</li><li>形参的顺序要合理(比如source与destination,除数与被除数)</li><li>如果传参是值的话建议用const&amp;,省去复制、构造与析构的过程</li><li>形参最好不要超过5个,而且参数最好有确定的类型与数目.</li></ul><p>返回值</p><ul><li>任何函数都要有类型,不返回就用void</li><li>函数名与返回值在语义方面不要冲突.比如别用getInt这种名字返回char型</li><li>对于赋值函数,使用“引用传递”返回对象;对于操作函数,使用“值传递”的方式返回对象.也就是根据实际情况选择<strong>值传递或者引用传递</strong></li></ul><p>函数</p><ul><li>函数入口要检查-使用断言assert</li><li>函数出口要检查return<ul><li>不能返回指向“栈内存”的“指针”或者“引用”</li><li>清楚返回的是什么</li><li>如果返回的是对象可以直接写 “创建对象并返回” 如: return Entity(s1);  这在效率上比 Entity temp(s1); return temp;要高得多.</li></ul></li><li>函数功能单一、短小精悍、避免记忆、出错处理要清晰</li></ul><p><strong>断言</strong></p><ul><li>一般用于<strong>捕捉非法情况</strong>而不是错误情况</li><li>防错设计</li></ul><p>比较——引用与指针</p><ul><li>引用是取别名,指针是地址</li><li>引用被创建的时候必须初始化(如<code>string&amp; name = m_Name;</code></li><li>引用不能为空;并且引用初始化之后不能改变引用的关系.</li></ul><h2 id="内存管理">内存管理</h2><p>规则</p><ul><li>用malloc或new申请内存之后,应该立即检查指针值是否为NULL.防止使用指针值为NULL的内存.</li><li>不要忘记为数组和动态内存赋初值.防止将未被初始化的内存作为右值使用.</li><li>避免数组或指针的下标越界,特别要当心发生“多1”或者“少1”操作.</li><li>动态内存的申请与释放必须配对,防止内存泄漏.</li><li><strong>用free或delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”</strong>.</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> *p = (<span class="type">int</span> *)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(<span class="type">int</span>));</span><br><span class="line"><span class="built_in">assert</span>(p!=<span class="literal">NULL</span>);</span><br><span class="line">*p = <span class="number">100</span>;</span><br><span class="line"><span class="built_in">free</span>(p);</span><br><span class="line"><span class="type">int</span> arr[<span class="number">5</span>] = &#123;<span class="number">0</span>&#125;;</span><br><span class="line">p = <span class="literal">NULL</span>;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="内容复制与比较">内容复制与比较</h3><p>规则</p><ul><li>数组与字符串等不能轻易用== 判断相等(因为== 只比较值而没有比较地址),除非重载了运算符</li><li>当数组作为函数的参数进行传递时,数组自动退化成同类型的指针</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">char</span> a[] = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line"><span class="type">char</span> b[<span class="number">10</span>];</span><br><span class="line"><span class="built_in">strcpy</span>(b, a);<span class="comment">//不能用b = a;</span></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">strcmp</span>(b, a) == <span class="number">0</span>) &#123;&#125;;<span class="comment">// 不能用if(b = a)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//指针</span></span><br><span class="line"><span class="type">int</span> num = <span class="number">10</span>;</span><br><span class="line"><span class="type">int</span> *a = &amp;num;</span><br><span class="line"><span class="type">int</span> len = <span class="built_in">strlen</span>(a);</span><br><span class="line"><span class="type">char</span>* p = (<span class="type">char</span>*)<span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(<span class="type">char</span>) * (len + <span class="number">1</span>));</span><br><span class="line"><span class="built_in">strcpy</span>(p, a);</span><br><span class="line"><span class="comment">//不要用p=a;</span></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">strcmp</span>(p, a) == <span class="number">0</span>) <span class="comment">// 不要用if(p = a)</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Fuction</span><span class="params">(<span class="type">char</span> a[<span class="number">100</span>])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">cout&lt;&lt;<span class="built_in">sizeof</span>(a)&lt;&lt;endl;<span class="comment">//结果是4而不是100</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>free 与delete</p><ul><li>这“两大护法”并没有把指针干掉,而是释放内存,地址还在(&quot;一屋传三代,人走屋还在_(:з」∠)“)</li></ul><p>指针的问题</p><ul><li>指针消亡了,并不表示它所指的内存会被自动释放.</li><li>内存被释放了,并不表示指针会消亡或者成了NULL指针.</li></ul><p>C中的malloc/free与C++中的new/delete</p><ul><li>new和delete会自动调用构造或者析构函数(如果有的话),而malloc与free没有</li><li>C语言只有malloc与free.</li></ul><h3 id="内存耗尽问题">内存耗尽问题</h3><p>虽然对于32位及以上的系统很难将内存耗尽,但是也需要做好报错处理(不能因为国力强盛就不修长城)</p><p>处理方法</p><ul><li>如果申请的内存为空,用return或者exit(1)终止</li><li>或者自定义处理函数 比如try catch</li></ul><h3 id="函数讲解">函数讲解</h3><p><strong>malloc</strong><br>函数原型为:<br><code>void * malloc(size_t size);</code><br>讲解</p><ul><li>void* 是泛指针,如果要调用的时候要将其显示转换</li><li>size是内存大小,一般用sizeof求出</li></ul><p>使用示例<br><code>int *p = (int*)malloc(sizeof(int)*length);</code></p><p><strong>free</strong><br>函数原型为<br><code>void free(void * memblock)</code></p><p><strong>new</strong><br>new内置了sizeof、类型转换、类型安全检查等功能,建议多使用</p><p><strong>delete</strong><br>不要漏掉[]<br>举例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">delete</span> []objects;<span class="comment">//正确</span></span><br><span class="line"><span class="keyword">delete</span> objects;<span class="comment">//错误,只删除了objects[0],漏掉了其他</span></span><br></pre></td></tr></table></figure><p><strong>心得</strong></p><blockquote><ol><li>越是害怕,越是要勇敢面对它(特指指针),战胜恐惧的最好方法就是面对恐惧,加油,奥利给</li><li>犯错不可怕,走过万千路,天堑变通途.</li></ol></blockquote><h2 id="C-高级特性">C++高级特性</h2><p><strong>重载与覆盖(overload and override)</strong></p><p>特征</p><table><thead><tr><th>类型</th><th>范围</th><th>函数名</th><th>参数</th><th>是否有virtual关键字</th></tr></thead><tbody><tr><td>重载</td><td>在同一个类中</td><td>相同</td><td>不同</td><td>可有可无</td></tr><tr><td>覆盖</td><td>在基类与派生类中</td><td>相同</td><td>相同</td><td>必须有</td></tr></tbody></table><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream.h&gt;</span></span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Base</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">f</span><span class="params">(<span class="type">int</span> x)</span></span>&#123;cout &lt;<span class="string">&quot;Base:f(int)&quot;</span>&lt;&lt;x &lt;endl;<span class="comment">//f被重载</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">f</span><span class="params">(<span class="type">float</span> x)</span></span>&#123;cout &lt;<span class="string">&quot;Base:f(float)&quot;</span>&lt;&lt;x &lt;endl;</span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">g</span><span class="params">(<span class="type">void</span>)</span></span>&#123;cout &lt;<span class="string">&quot;Base:g(void)&quot;</span>&lt;&lt;endl;</span><br><span class="line">&#125;:</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Derived</span> : <span class="keyword">public</span> Base</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function"><span class="keyword">virtual</span> <span class="type">void</span> <span class="title">g</span><span class="params">(<span class="type">void</span>)</span></span>&#123;cout &lt;<span class="string">&quot;Derived:g(void)&quot;</span>&lt;&lt;endl;&#125;<span class="comment">//派生类覆盖原来基类的g函数,一旦后面通过派生类调用g函数,统一都是重写后的函数</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>错误高发区：隐藏</strong><br>简单来说就是想通过派生类调用基类的函数却发现调用的都是派生类的函数,导致编译失败,在以下情况下会发生</p><ul><li>派生类的函数与基类的函数同名,但是参数不同</li><li>派生类的函数与基类的函数同名,参数相同,但是基类函数没有virtual</li></ul><p><strong>参数的缺省值</strong><br>缺省值就是默认值(<strong>default</strong>),中文翻译不准确,尽可能使用英文.</p><p>规则</p><ul><li>参数的default值只能出现在函数的声明中</li><li>default值从后往前写</li></ul><p>运算符重载</p><p><strong>函数内联</strong>(inline)<br>函数内联具有宏效率,又有效解决了宏无法调试和安全性的问题.<strong>建议在C++中使用内联取代宏</strong>(assert除外)</p><p><strong>使用说明</strong></p><ul><li>inline必须必须<strong>和函数定义体放在一起</strong>才能使函数成为内联函数.</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">add</span><span class="params">(<span class="type">const</span> <span class="type">int</span>&amp; x,<span class="type">const</span> <span class="type">int</span>&amp; y)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> x+y;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>特别的：虽然在类中定义的函数自动变成内联函数,但是一般不会在类中定义函数,如果需要内联记得在定义处加上inline.</li><li>内联是<strong>用空间换时间</strong></li></ul><h2 id="类的构造函数、析构函数和赋值函数">类的构造函数、析构函数和赋值函数</h2><p>简单示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">String</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="built_in">String</span>(<span class="type">const</span> <span class="type">char</span> *str = <span class="literal">NULL</span>);<span class="comment">//普通构造函数</span></span><br><span class="line"><span class="built_in">String</span>(<span class="type">const</span> String &amp;other);/拷贝构造函数</span><br><span class="line">~<span class="built_in">String</span> (<span class="type">void</span>);<span class="comment">//析构函数</span></span><br><span class="line">String &amp; operate =(<span class="type">const</span> String &amp;other);<span class="comment">//赋值函数 其实是重载=</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"><span class="type">char</span> *m_data;<span class="comment">//用于保存字符串</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h2 id="类的继承与组合">类的继承与组合</h2><p>简单讲解对象(object)、类(class)和实例(instance)的关系<br>对象就是“房子”,类就是设计房子的“蓝图”,对象是类的一个实例,根据“蓝图”可以盖很多的“房子”.<br>所谓<strong>面向对象编程</strong>,就是设计“图纸”.</p><p><strong>继承的规则</strong></p><ul><li>不相关的两个类不要继承(“公若不弃,愿拜为义父”doge)</li><li>在逻辑上B是A的一种,并且A的所有属性和功能都对A有意义,就允许B继承A.比如虽然鸵鸟是鸟,但是“飞”的功能对鸵鸟是多余的,这种情况下最好不要继承与鸟</li></ul><p><strong>组合的规则</strong></p><ul><li>若在逻辑上A是B的“一部分”(a part of),则不允许B从A派生,而是要用A和其它东西组合出B.比如电池、屏幕和芯片是手机的一部分,就用这些类组合起来生成手机类,而不是让手机“<strong>拜电池等为义父</strong>”</li></ul><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Cell</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">charge</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Screen</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Look</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Chip</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Run</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//手机类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Phone</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">charge</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Look</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Rum</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">Cell m_cell;</span><br><span class="line">Screen m_screen;</span><br><span class="line">Chip m_chip;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="编程经验">编程经验</h2><h3 id="常用const">常用const</h3><p>注意</p><ul><li>const只能修饰输入参数</li><li>对于值传递的参数无需使用const修饰</li><li>对于非内部数据类型(就是C|C++标准库之外的类型)的输入参数.可以使用<strong>const 类型&amp;</strong> 的方式在提高效率的同时不改变参数内容.<ul><li>比如int确实没必要使用const int &amp;.,内部数据类型没有构造与析构,复制也很快,不需要多此一举</li></ul></li><li>函数返回值如果是值传递,不需要用const修饰</li><li>不修改成员属性的函数都要加const</li></ul><h1>个人思考</h1><p>写代码就像是写作文,理论上只要表达意思正确(也就是程序能运行并达到理想效果),什么首行缩进、分段都不影响文章的质量,但是作文是要修改的(程序要维护),是要给人看的(别人要使用你的程序),此时语句(代码)就是交流的主要工具,语句的逻辑是什么?怎样表达就能让对方理解?怎样吸引读者阅读你的文章?怎样减少语病与错误?这是我们在写作文的时候经常思考的问题,编程也是一样.</p><p>接下来就从写好一篇文章开始讲解代码是什么.首先,写作者的名字,这就引出了“<strong>版权和版本</strong>“的声明,表明作品是你写的,作品处于哪个阶段.然后,给人物取名字,一般老师会让学生用什么典雅的古文等方法给人物取名,不过在计算机这里就不适用了,要简洁直白,能叫&quot;many&quot;就不要用&quot;quite a number of&quot;,又不是给英语作文凑字数(doge)</p><p>然后就要开始准备工作了,如果我们写的是人物传记,就要交代人物名字及其相关信息(声明及初始化变量),比如“廉颇者,赵之良将也”,声明一个Person类的变量名为“廉颇”,并将“赵国”“良将”作为参数构造了一个Person的实例对象——人.有的还会在正文之前写时间地点等,比如“元丰六年,余左迁……”(出自《琵琶行》)就是定义(define)”今年“为”元丰六年“,以后所有的”今年“都会被”元丰六年“等效代替.</p><p>以下以《廉颇蔺相如列传》第一段为例.</p><p>接下来我用“保安三问”(<strong>你是谁?你去哪?你干嘛?</strong>)来讲解如何写代码.</p><p>“廉颇者,赵之良将也”.首先,<strong>第一问“廉颇是谁?”</strong> ,我们需要给廉颇一个定义,是人是神还是鬼,是符号还是具体的事物?理论上都可以,但是从复用的角度和理解的角度来看,用“人”更加通俗易懂,即定义成“人”类(class)或者是结构体,这里以面向对象为主要编程思想,采用”类“来构造一个”人“. 然后,声明和定义一个“人”类,由于高质量编程的需要,最好将声明与定义放在不同的文件里面,类比图书放在不同的类别,都是为了后续减少维护成本.但是构造类的过程中有一点问题,类里面应该放点什么东西呢?我的建议是,随着”故事“的展开不断更新”人“类,毕竟人是会成长的,想要一开始一劳永逸只会顾此失彼.</p><p><strong>第二问“廉颇去哪?”</strong> 一般来说,所有的代码都直接或者间接在main函数里面.这里的“廉颇”也不例外.</p><p><strong>第三问”廉颇干嘛?“</strong> 第一句没有交代廉颇的行为,但是交代了廉颇的”特性“(属性),这就提醒”人“类可以”更新“了,比如添加”国籍(nationality)“、”地位(status)“属性并公开(双料特工可以不公开doge),不过又有问题了,这些属性应该是哪一种变量呢?string、int还是class呢?我的建议是,在日常生活中常以文字出现的用字符串(char[] string等),以数字出现的(比如成绩)用整型(比如int)或者浮点型(比如double).不过仅作参考,<strong>合适的才是最好的</strong>.好了,现在我们给“人”类添加了nationality和status属性,但是我们要“构造”一个“廉颇”啊,不能只把“廉颇”的特性给女娲却不告诉她怎样“玩泥巴”吧,也就是<strong>声明并定义有参构造</strong>(教女娲如何用泥巴塑造廉颇),怎样定义呢?“廉颇”要什么,就给女娲什么,廉颇要名字、要身份、要国籍,就给他名字(m_name = name;).现在,“人”类的基本蓝图已经有了,也告诉女娲怎样“捏一个人类“了,接下来就要将廉颇的特性传递给构造函数了.如下,成功创建了”廉颇“.用cout输出一下其特性,完美.</p><p>廉颇有了,要<strong>干什么</strong>呢?伐齐！这是一个动作,可以用一个<strong>函数</strong>来表示,那么函数应该是类中的函数还是外面的函数呢(<strong>保安第二问</strong>)?我的建议是,看谁复用性更强,毕竟人都喜欢偷懒,这里用类中的函数,毕竟之后蔺相如”人“也要”攻打“齐国.对于类的定义与实现,也是同理的<strong>保安三问</strong>,是什么?在哪里?干什么?是什么——返回什么类型,要什么参数,名字是什么;在哪里——函数声明与定义在哪里;干什么——实现了什么功能.<strong>不停追问自己,然后不断完善代码</strong>.<strong>伐</strong>字实现了,又到”齐“了,看起来好像是string,又感觉可以是class,用什么比较好呢?我的建议是,从宏观看”齐“的”地位“,即”齐“出现频率高不高,包含的东西多不多,以此配位,从全文来看,”齐“明显是高频词汇,应该重视,string不配修饰”齐“,那就用类(class)吧.同理<strong>保安三问</strong>创建”国家(country)“类.添加防御力(m_defenseValue)和名字(name)属性等.</p><p>下一句是“大破之”是结果,但是<strong>过程</strong>是什么呢?也就是结果的“因”是什么呢?这里实现的方法就见仁见智了,可以通过数值的比较,可以是特定的属性触发,甚至可以随机判定输赢,这里就用游戏中常用的“数值”来比较,用判断语句(if)判定.另一个结果是”拜为上卿,以勇气闻於诸侯“,这里强调的属性是”上卿“”闻(出名的意思)“看”人“类中有没有,有一个status,但是没有”出名“的属性,可以添加一个,<strong>根据保安三问定律</strong>,<strong>取</strong>”出名“的属性为int,名字是m_fame,用数值代表出名程度.然后在if中添加结果(将m_fame的值提升,将m_status的值改变),最后根据m_fame的值输出语句.至此,程序完结.</p><p><strong>示例如下</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在Person.h中</span></span><br><span class="line"><span class="comment">//定义“人”类.</span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;Country.h&quot;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">string m_nationality;<span class="comment">//国籍</span></span><br><span class="line"><span class="type">int</span> m_ability = <span class="number">1</span>;<span class="comment">//能力值 范围1-5 越大能力越强</span></span><br><span class="line">string m_name;<span class="comment">//名字</span></span><br><span class="line">string m_status;<span class="comment">//地位</span></span><br><span class="line"><span class="type">int</span> fame = <span class="number">1</span>;<span class="comment">//名声 范围1-5</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="comment">//构造</span></span><br><span class="line"><span class="built_in">Person</span>(<span class="type">void</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//有参构造</span></span><br><span class="line"><span class="built_in">Person</span>(string name, string nationality, <span class="type">int</span> ability, string status);</span><br><span class="line"></span><br><span class="line"><span class="comment">//攻击函数</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Attack</span><span class="params">(Country nation)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//析构</span></span><br><span class="line">~<span class="built_in">Person</span>(<span class="type">void</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在Person.cpp文件中(也就是实现类中)</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _CRT_SECURE_NO_WARNINGS</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;Person.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Person::<span class="built_in">Person</span>(string name, string nationality, <span class="type">int</span> ability,string status)</span><br><span class="line">&#123;</span><br><span class="line">m_name = name;</span><br><span class="line">m_nationality = nationality;</span><br><span class="line">m_ability = ability;</span><br><span class="line">m_status = status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person::<span class="built_in">Person</span>(<span class="type">void</span>)</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person::~<span class="built_in">Person</span>(<span class="type">void</span>)</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Person::Attack</span><span class="params">(Country nation)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (m_ability&gt; nation.m_defenseValue)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>“赵惠文王十六年”<br><code>int to_year = 16;</code></p><p>“廉颇为赵将伐齐”</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在Country.h 文件中</span></span><br><span class="line"><span class="comment">//定义国家类</span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Country</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="type">int</span> m_defenseValue = <span class="number">1</span>;<span class="comment">//国家防御力</span></span><br><span class="line">string m_name;<span class="comment">//国家名字</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="built_in">Country</span>(<span class="type">void</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">Country</span>(string name, <span class="type">int</span> defenseValue);</span><br><span class="line"></span><br><span class="line">~<span class="built_in">Country</span>(<span class="type">void</span>);</span><br><span class="line"></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在Country.cpp</span></span><br><span class="line"><span class="comment">//国家类实现</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _CRT_SECURE_NO_WARNINGS</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;Person.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Person::<span class="built_in">Person</span>(string name, string nationality, <span class="type">int</span> ability,string status)</span><br><span class="line">&#123;</span><br><span class="line">m_name = name;</span><br><span class="line">m_nationality = nationality;</span><br><span class="line">m_ability = ability;</span><br><span class="line">m_status = status;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person::<span class="built_in">Person</span>(<span class="type">void</span>)</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Person::~<span class="built_in">Person</span>(<span class="type">void</span>)</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Person::Attack</span><span class="params">(Country nation)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (m_ability&gt; nation.m_defenseValue)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>“大破之,取阳晋,拜为上将,以勇气闻於诸侯”</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在main.cpp文件里面</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> _CRT_SECURE_NO_WARNINGS</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;Person.h&quot;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&quot;Country.h&quot;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">//自定义函数库</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//创建“廉颇”与“蔺相如”</span></span><br><span class="line"><span class="function">Person <span class="title">LianPo</span><span class="params">(<span class="string">&quot;廉颇&quot;</span>, <span class="string">&quot;Zhao&quot;</span>, <span class="number">5</span>,<span class="string">&quot;良将&quot;</span>)</span></span>;</span><br><span class="line"><span class="function">Person <span class="title">LiXiangRu</span><span class="params">(<span class="string">&quot;蔺相如&quot;</span>, <span class="string">&quot;Zhao&quot;</span>, <span class="number">5</span>, <span class="string">&quot;舍人&quot;</span>)</span></span>;</span><br><span class="line"><span class="comment">//输出“廉颇”的基本信息</span></span><br><span class="line">cout &lt;&lt; LianPo.m_name &lt;&lt; <span class="string">&quot;者,&quot;</span> &lt;&lt; LianPo.m_nationality &lt;&lt; <span class="string">&quot;之&quot;</span> &lt;&lt; LianPo.m_status &lt;&lt; <span class="string">&quot;也&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="comment">//创建齐国</span></span><br><span class="line"><span class="function">Country <span class="title">Qi</span><span class="params">(<span class="string">&quot;qi&quot;</span>, <span class="number">3</span>)</span></span>;</span><br><span class="line"><span class="comment">//赵惠王十六年</span></span><br><span class="line"><span class="type">int</span> to_year = <span class="number">16</span>;</span><br><span class="line"><span class="comment">//廉颇为赵将伐齐</span></span><br><span class="line"><span class="type">bool</span> ret = LianPo.<span class="built_in">Attack</span>(Qi);</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; LianPo.m_name &lt;&lt; <span class="string">&quot;对&quot;</span> &lt;&lt; Qi.m_name &lt;&lt; <span class="string">&quot;发起攻击&quot;</span> &lt;&lt; endl;</span><br><span class="line"><span class="comment">//判断讨伐是否成功</span></span><br><span class="line"><span class="keyword">if</span> (ret)</span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;大破之&quot;</span> &lt;&lt; endl;</span><br><span class="line">LianPo.m_status = <span class="string">&quot;上卿&quot;</span>;</span><br><span class="line">cout &lt;&lt; LianPo.m_name &lt;&lt; <span class="string">&quot;被拜为&quot;</span> &lt;&lt; LianPo.m_status &lt;&lt; endl;</span><br><span class="line">LianPo.fame = <span class="number">4</span>;</span><br><span class="line"><span class="comment">//判断名声等级</span></span><br><span class="line"><span class="keyword">if</span> (LianPo.fame &gt;= <span class="number">4</span>)</span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;以勇气闻於诸侯&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>看到这里,你会有一个问题,为什么要用写作来形容代码的编写过程呢?对以中文为母语的人可能难以理解,但是对于以英语为母语的人早已习以为常,甚至达到了“美国人刚出生就会写代码”的程度.对他们来说,写代码就是写英语作文,无非是语法更严格,字数变更少,语句更加讲逻辑,对我们来说就是在“写天书”.这里想说的是,将写代码看做是写英语作文,可以<strong>有效提高写代码的逻辑性</strong>,而且,一旦你认为自己写的是一篇作文,要传阅给所有人看,你就会不自觉“美化”你的作文(代码),<strong>在无形之中,你对自己写的作文(代码)提高了要求</strong>。我以写作为例,更多的是想让你感受一下<strong>保安三问定律</strong>在写代码方面的作用和按照一定的规则写代码的好处,毕竟代码就是语句,多行代码构成段落,多个段落构成故事,<strong>故事都有起因经过结果,保安定律就是为了回答这三者究竟是什么，规则限定我们写故事写在哪，怎样写易读性更强</strong>。也许自己的故事有缺陷,也许编程能力有限,但总是能引导我们走向文章的结尾,给老师(编译器)和他人一个满意的答卷.</p><h1>参考资料</h1><ul><li>《高质量C、C++》 林锐</li><li>《C++ Prime Plus(第六版)》</li></ul>]]></content>
    
    
    <summary type="html">学习大佬是如何提升C&#92;C++代码的质量，为后续其他高级计算机语言的开发打下基础和养成规范编程的习惯</summary>
    
    
    
    <category term="C++" scheme="https://lloydkai.cn/categories/C/"/>
    
    
    <category term="C" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>hexo博客系列(四)测试博客功能</title>
    <link href="https://lloydkai.cn/posts/blog-series-four/"/>
    <id>https://lloydkai.cn/posts/blog-series-four/</id>
    <published>2025-05-20T13:24:34.000Z</published>
    <updated>2026-04-23T01:47:11.029Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/ESnx9lyZuJ83XpA.jpg" alt></p><h2 id="测试博客功能">测试博客功能</h2><h3 id="测试图片">测试图片</h3><p><strong>阿里云图片测试</strong></p><p>得出结论,阿里云图床在github.io上无法显示，可能要使用国内的服务器才能比较快速响应</p><p><strong>本地图片测试</strong></p><p>由于github镜像源限制的问题，<strong>不推荐站主们使用github作为文件或者是图片的镜像源，而是使用比较正规的托管平台或者图片上传平台</strong>。</p><p><strong>标签外挂测试图片</strong></p><div class="gallery-container" data-type="data" data-button data-limit="10" data-first="10">    <div class="gallery-items">[{"url":"https://s2.loli.net/2024/06/14/4RrcPzbG3fsqyC6.png","alt":"3.png","title":""}]</div>  </div><p><strong>图床图片测试</strong></p><p><img src="https://s2.loli.net/2024/10/24/MQ6gGn4LtBDyduJ.png" alt="苍之彼方的四重奏.png"></p><h3 id="测试系列文章">测试系列文章</h3><ol class="series-items"><li><a href="/posts/blog-series-one/" title="hexo博客系列(一)更新公告">hexo博客系列(一)更新公告</a></li><li><a href="/posts/blog-series-three/" title="hexo博客系列(三)博客写作指南">hexo博客系列(三)博客写作指南</a></li><li><a href="/posts/blog-series-two/" title="hexo博客系列(二)博客创建指南">hexo博客系列(二)博客创建指南</a></li><li><a href="/posts/blog-series-five/" title="hexo博客系列(五)博客部署">hexo博客系列(五)博客部署</a></li><li><a href="/posts/blog-series-four/" title="hexo博客系列(四)测试博客功能">hexo博客系列(四)测试博客功能</a></li></ol><h3 id="标签外挂测试">标签外挂测试</h3><blockquote><p>本以下基于hexo+butterfly的主题，其他的主题请读者自行查阅有关资料</p></blockquote><p>官方文档：<a href="https://butterfly.js.org/posts/ceeb73f/">Butterfly 文檔(四) 標簽外挂 | Butterfly</a></p><ol><li>Note (Bootstrap Callout)</li></ol><p>个人使用，感觉比较适合知识的分层结构，比如我博客里面的《英语语法(英语兔版)》</p><ol start="2"><li>tag-hide</li></ol><p>个人感觉比较适合于问答类型或者是部分内容较多，需要的时候再展开的文章内容。测试如下</p><p><strong>Block测试</strong></p><p>查看答案</p><div class="hide-block"><button type="button" class="hide-button" style>查看答案</button><div class="hide-content"><p>答案就在你心中</p></div></div><p><strong>Toggle测试</strong></p><details class="toggle"><summary class="toggle-button" style>Butterfly安裝方法</summary><div class="toggle-content"><p>在你的博客根目錄裏</p><p><code>git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly</code></p><p>如果想要安裝比較新的 dev 分支，可以</p><p><code>git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/Butterfly</code></p></div></details><p><strong>Mermaid测试</strong></p><p>这是和图表有关的标签，可以画流程图，时序图等</p><p>注意要先写<code>&#123;% mermaid %&#125; &#123;% endmermaid %&#125;</code> 然后就在这两个标签内写相关代码。</p><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    sequenceDiagram    participant Alice    participant Bob    Alice-&gt;&gt;John: Hello John, how are you?    loop HealthCheck        John-&gt;&gt;John: Fight against hypochondria    end    Note right of John: Rational thoughts &lt;br&#x2F;&gt;prevail!    John--&gt;&gt;Alice: Great!    John-&gt;&gt;Bob: How about you?    Bob--&gt;&gt;John: Jolly good!  </pre></div><p><strong>乐谱测试</strong></p><div class="abc-music-sheet">X:1T:alternate headsM:CL:1/8U:n=!style=normal!K:C treble style=rhythm&quot;Am&quot; BBBB B2 B&gt;B | &quot;Dm&quot; B2 B/B/B &quot;C&quot; B4 |&quot;Am&quot; B2 nGnB B2 nGnA | &quot;Dm&quot; nDB/B/ nDB/B/ &quot;C&quot; nCB/B/ nCB/B/ |B8| B0 B0 B0 B0 |]%%text This translates to:[M:C][K:style=normal][A,EAce][A,EAce][A,EAce][A,EAce] [A,EAce]2 [A,EAce]&gt;[A,EAce] |[DAdf]2 [DAdf]/[DAdf]/[DAdf] [CEGce]4 |[A,EAce]2 GA [A,EAce] GA |D[DAdf]/[DAdf]/ D[DAdf]/[DAdf]/ C [CEGce]/[CEGce]/ C[CEGce]/[CEGce]/ |[CEGce]8 | [CEGce]2 [CEGce]2 [CEGce]2 [CEGce]2 |]GAB2 !style=harmonic![gb]4|GAB2 [K: style=harmonic]gbgb|[K: style=x]C/A,/ C/C/E C/zz2|w:Rock-y did-nt like that</div><p><strong>测试自带的chartjs</strong>——可以实现动态效果，建议使用。</p><div class="chartjs-container chartjs-abreast" data-chartjs-id data-width="40%">            <pre class="chartjs-src" hidden>{    &quot;type&quot;: &quot;pie&quot;,    &quot;data&quot;: {        &quot;labels&quot;: [            &quot;编程&quot;,            &quot;音乐&quot;,            &quot;阅读&quot;,            &quot;游戏&quot;,            &quot;健身&quot;,            &quot;旅游&quot;        ],        &quot;datasets&quot;: [            {                &quot;label&quot;: &quot;喜爱指数&quot;,                &quot;data&quot;: [                    30,                    24,                    19,                    14,                    9,                    4                ],                &quot;backgroundColor&quot;: {                    &quot;dark-mode&quot;: [                        &quot;rgba(255, 99, 132, 0.5)&quot;,                        &quot;rgba(54, 162, 235, 0.5)&quot;,                        &quot;rgba(255, 206, 86, 0.5)&quot;,                        &quot;rgba(75, 192, 192, 0.5)&quot;,                        &quot;rgba(153, 102, 255, 0.5)&quot;,                        &quot;rgba(255, 159, 64, 0.5)&quot;                    ],                    &quot;light-mode&quot;: [                        &quot;rgba(255, 99, 132, 0.2)&quot;,                        &quot;rgba(54, 162, 235, 0.2)&quot;,                        &quot;rgba(255, 206, 86, 0.2)&quot;,                        &quot;rgba(75, 192, 192, 0.2)&quot;,                        &quot;rgba(153, 102, 255, 0.2)&quot;,                        &quot;rgba(255, 159, 64, 0.2)&quot;                    ]                },                &quot;borderColor&quot;: {                    &quot;dark-mode&quot;: [                        &quot;rgba(255, 99, 132, 1)&quot;,                        &quot;rgba(54, 162, 235, 1)&quot;,                        &quot;rgba(255, 206, 86, 1)&quot;,                        &quot;rgba(75, 192, 192, 1)&quot;,                        &quot;rgba(153, 102, 255, 1)&quot;,                        &quot;rgba(255, 159, 64, 1)&quot;                    ],                    &quot;light-mode&quot;: [                        &quot;rgba(255, 99, 132, 1)&quot;,                        &quot;rgba(54, 162, 235, 1)&quot;,                        &quot;rgba(255, 206, 86, 1)&quot;,                        &quot;rgba(75, 192, 192, 1)&quot;,                        &quot;rgba(153, 102, 255, 1)&quot;,                        &quot;rgba(255, 159, 64, 1)&quot;                    ]                }            }        ]    },    &quot;options&quot;: {        &quot;plugins&quot;: {            &quot;legend&quot;: {                &quot;labels&quot;: {                    &quot;color&quot;: {                        &quot;dark-mode&quot;: &quot;rgba(255, 255, 255, 0.8)&quot;,                        &quot;light-mode&quot;: &quot;rgba(0, 0, 0, 0.8)&quot;                    }                }            }        }    }}</pre>            <div class="chartjs-desc"><p>除了<strong>计算机编程</strong>外，我想不出还有其他让我感兴趣的工作。<br>我可以无中生有地创造出<strong>精美的范式</strong>和<strong>结构</strong>，<br>在此过程中也解决了无数的小谜团。<br><span style="font-size:0.8em;color: var(--sep-secondtext);">I can’t think of any other job other than <strong>computer programming</strong> that interests me.<br>I can create <strong>beautiful paradigms</strong> and <strong>structures</strong> out of nothing,<br>Countless small mysteries are also solved in the process.</span></p></div>          </div><p><strong>tab演示</strong></p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">test1 1</button><button type="button" class="tab">test1 2</button><button type="button" class="tab">test1 3</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>This is Tab 1.</strong></p></div><div class="tab-item-content"><p><strong>This is Tab 2.</strong></p></div><div class="tab-item-content"><p><strong>This is Tab 3.</strong></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h3 id="其他功能测试">其他功能测试</h3><p><strong>按钮button测试</strong></p><div class="btn-center"><a class="btn-beautify outline larger" href="https://butterfly.js.org/" title="Butterfly"><i class="far fa-hand-point-right"></i><span>Butterfly</span></a></div><p><strong>文字高亮</strong></p><mark class="hl-label color">text</mark> ,颜色可选default/blue/pink/red/purple/orange/green<mark class="hl-label red">红色</mark>]]></content>
    
    
    <summary type="html">主要用于测试hexo新功能和butterfly主题相关的一些新特性,在不确定效果的时候优先以本文件作为测试用例</summary>
    
    
    
    <category term="blog" scheme="https://lloydkai.cn/categories/blog/"/>
    
    
    <category term="blog" scheme="https://lloydkai.cn/tags/blog/"/>
    
    <category term="hexo" scheme="https://lloydkai.cn/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>算法系列(四)从零开始的算法刷题生活</title>
    <link href="https://lloydkai.cn/posts/algorithm-restart/"/>
    <id>https://lloydkai.cn/posts/algorithm-restart/</id>
    <published>2025-03-02T12:50:14.000Z</published>
    <updated>2026-04-23T01:45:40.606Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/UoQ1dIlXtehfvjx.jpg" alt></p><blockquote><p>之前的练习是C++，从现在开始要用Java做算法题了，以后每天都要花30min到1h左右在算法上，这东西就是要积累</p></blockquote><h1>算法基础</h1><h2 id="提醒">提醒</h2><ol><li><strong>对于急需找工作的情况，建议优先刷leetcode的hot100题，而对于绝大多数的求职者来说，我们的算法能力只需要达到70-80左右即可，不要花大量的时间在算法上，而是有目的的学习</strong></li><li>刷leetcode的最好时间是十年以前，其次就是现在。<strong>不能再堕落下去了，一定要出重拳</strong>！o(<em>￣▽￣</em>)o</li><li>既然我们的目的是70-80分，对于比较偏僻的知识点这里就不再提及(除非是面试中出现过的)</li></ol><hr><blockquote><p>引自labuladong网站上的一句话</p></blockquote><div class="note info default simple"><p><strong>复习是一定需要的。我建议在刷完一个习题章节后，隔 3 天左右一定要再回来做一遍习题。</strong></p><p>因为你之前已经过了一遍，所以复习时尽量不要看我的解法，自己思考求解。如果有做不出来的，那就看答案，然后过几天再回来做，直到都能求解出来为止。</p><p><strong>切记不要背题</strong></p><p>算法这个东西不是八股文，千万不要妄图背题，这样是没有用的。<strong>应该去理解算法的原理，而不是具体的解题代码</strong>。比方说，不要因为你记得上次这里使用的是 <code>&lt;=</code> 号，所以回来复习的时候直接用 <code>&lt;=</code>，这是没用的。</p><p>忘了题目的解法代码，这是好事啊，那你就自己分析，一边思考一边写嘛。为什么要用 <code>&lt;=</code>，你要能说出个所以然来，这样才叫复习呀，否则就是囫囵吞枣死记硬背，没用的。<mark class="hl-label red">会证明远比比会记忆更重要，一证胜万题</mark></p></div><hr><h3 id="个人刷题感悟">个人刷题感悟</h3><ol><li>任何数据结构，其<strong>特点既是它的优点也是它的缺点</strong>。比如数组的优点是连续，可以快速访问元素，缺点也是连续，扩容和增删时非常麻烦。</li><li>时间复杂度和空间复杂度对立统一，有得便有舍。</li><li>对于分治法的最好理解是&quot;<strong>树上只有一片叶子，和剩下的叶子</strong>&quot;</li><li>计算机的思维在于科学的穷举，<strong>穷举是所有算法题的最终解法</strong>。</li><li>一开始千万不要陷入实现的细节，像做数学题一样，联想性质，定义，条件，一步步推理，作答。</li></ol><hr><h2 id="数据结构的实现">数据结构的实现</h2><blockquote><p>建议读者可以买一本《大话数据结构》的书并将上面所有的代码敲一遍，再回头看以前写过的算法题会有不一样的感受，站主之前就是这么学习数据结构的，即使我不是计算机专业的，但是我敲过的代码不比科班的少&lt;(￣︶￣)&gt;</p></blockquote><div class="note warning dafault simple"><p>后面的算法和数据结构将不再参考国内的教材(<s>因为太垃圾</s>) ，如果读者在YouTube或者是MIT、伯克利大学看过对应的CS公开课(比如CS61A)，就会意识到国内和国外的计算机教育差距有多么大，<strong>为了以后的发展，建议优先选择国外教材和课程</strong>。</p></div><p><strong>以下实现语言主要为Java</strong>，部分情况下会结合C/C++进行底层讲解，其他语言的读者可以去<a href="https://labuladong.online/algo/home/">labuladong的网站</a>上找对应的代码实现。</p><p>正在更新中</p><h3 id="静态数组与动态数组">静态数组与动态数组</h3><p><strong>相关的总结</strong></p><ol><li><p>为什么数组的索引从 0 开始？就是方便取地址。<code>arr[0]</code> 就是 <code>arr</code> 的首地址，从这个地址往后的 4 个字节(<strong>一个int变量的大小，也就是指针所指对象的大小</strong>)存储着第一个元素的值；<code>arr[1]</code> 就是 <code>arr</code> 的首地址加上 <code>1 * 4</code> 字节，也就是第二个元素的首地址，这个地址往后的 4 个字节存储着第二个元素的值。<code>arr[2], arr[3]</code> 以此类推(英文教材将其称为<strong>offset</strong>,也就是偏移量的意思)</p></li><li><p>因为<strong>数组的名字 <code>arr</code> 就指向整块内存的首地址</strong>，所以数组名 <code>arr</code> 就是一个指针。你直接取这个地址的值，就是第一个元素的值。也就是说，<code>*arr</code> 的值就是 <code>arr[0]</code>，即第一个元素的值。</p></li><li><p>为什么国内的教材常常用memset初始化数组？如果不用 <code>memset</code> <strong>这类函数</strong>初始化数组的值，那么数组内的值是不确定的。因为 <code>int arr[10]</code> 这个语句只是请操作系统在内存中开辟了一块连续的内存空间，但是其中的内容你是不知道的。</p></li></ol><p>示例：比如以下代码</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> a;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;%d&quot;</span>,a);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在VS中会报错提示“<strong>使用了未初始化的内存a</strong>&quot;,在其他编译器可能能运行并打印一个比较大的值(不唯一)。</p><hr><p><strong>动态数组</strong></p><p><strong>动态数组底层还是静态数组，只是自动帮我们进行数组空间的扩缩容，并把增删查改操作进行了封装，让我们使用起来更方便而已</strong>。比如C++中的vector容器。虽然国内的教材喜欢用指针来实现动态数组，但其本质仍然是静态数组。</p><p><a href="https://github.com/lloyd-kai/PracticeAlgorithmInJava/blob/main/src/main/java/myArrayList.java">我的实现如下</a></p><h3 id="单链表与双链表">单链表与双链表</h3><p>常见的用力扣上C++定义的链表如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">ListNode</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="type">int</span> val;<span class="comment">//节点的数据域，相当于data</span></span><br><span class="line">ListNode* next;</span><br><span class="line"><span class="built_in">ListNode</span>(<span class="type">int</span> x) :<span class="built_in">val</span>(x), <span class="built_in">next</span>(<span class="literal">NULL</span>) &#123;&#125; <span class="comment">//显式初始化函数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//实际常用的链表节点</span></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> E&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Node</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">E val;</span><br><span class="line">Node* next;</span><br><span class="line">Node* prev;</span><br><span class="line"></span><br><span class="line"><span class="built_in">Node</span>(Node* prev, E element, Node* next)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">this</span>-&gt;val = element;</span><br><span class="line"><span class="keyword">this</span>-&gt;next = next;</span><br><span class="line"><span class="keyword">this</span>-&gt;prev = prev;</span><br><span class="line">&#125;</span><br><span class="line">&#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>需要注意的是，国内的教材喜欢用宏定义(比如ElemType)，让你可以指定val为任意数据类型，而在C++中有<strong>泛型编程</strong>的特性，可以用template实现。</p><p>其中最为巧妙的构思是<strong>设置虚拟头尾节点</strong>。如果你不设置虚拟头尾节点，在涉及到插入的时候就要分三种情况，分别是头部插入、中间插入和尾部插入，在代码中就需要用三个if实现，而牺牲一部分空间可以换来统一的处理——全部视为中间插入，在算法训练和实际应用中也是以虚拟节点使用居多。</p><h3 id="循环数组-环形数组">循环数组(环形数组)</h3><p>需要注意的是，<strong>循环数组的本质还是数组</strong>，通过start和end”指针”最大限制利用分配的连续的空间。当 <code>start, end</code> 移动超出数组边界（<code>&lt; 0</code> 或 <code>&gt;= arr.length</code>）时，我们可以通过<strong>求模运算</strong> <code>%</code> 让它们转一圈到数组头部或尾部继续工作，这样就实现了环形数组的效果，<strong>其他的全是实现的具体细节，完全可以自行推导，本质就这样</strong>，不要死背代码，真正理解内核才能一招破万题。</p><p>在《数据结构》这本书中，一般是使用front和rear作为指针，而且书中会强调，<strong>front指向第一个元素，rear指向最后一个元素的下一个空间</strong>，这样专门在数组中留下一个空间不填是为了<strong>区分判空和判满的逻辑</strong>,即</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">isEmpty</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> front == rear;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">isFull</span><span class="params">()</span></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> (rear<span class="number">+1</span>)%size == front;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中size是整个数组的大小。当然也可以不留空间，那么判断满的条件就要变化，一般用<code>return count == size;</code> 判断，其中count是元素数量。</p><p><a href="https://github.com/lloyd-kai/PracticeAlgorithmInJava/blob/main/src/main/java/MyCycleArray.java">实现如下</a></p><h3 id="队列与栈">队列与栈</h3><p>【概念】：队列和栈都是「操作受限」的数据结构，比如队列只能一端删除，一端添加。需要注意的是<strong>受限不是劣势</strong>，反而如果选择恰当，表现能比全能的数据结构还要出色。</p><p>至于实现，可以去看《数据结构》这本书，我因为408考研写过很多次，这里就不写了。</p><h3 id="哈希表">哈希表</h3><p>【概念】：需要注意的是：<strong>哈希表和我们常说的 Map（键值映射)不是一个东西</strong>。</p><p>这一点用 Java 来讲解就很清楚，<code>Map</code> 是一个 Java 接口，仅仅声明了若干个方法，并没有给出方法的具体实现：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">interface</span> <span class="title class_">Map</span>&lt;K, V&gt; &#123;</span><br><span class="line">    V <span class="title function_">get</span><span class="params">(K key)</span>;</span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">put</span><span class="params">(K key, V value)</span>;</span><br><span class="line">    V <span class="title function_">remove</span><span class="params">(K key)</span>;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Map <strong>接口本身只定义了键值映射的一系列操作</strong>，HashMap 这种数据结构根据自身特点实现了这些操作。还有其他数据结构也实现了这个接口，比如 <code>TreeMap</code>、<code>LinkedHashMap</code> 等等。也就是说，<strong>哈希表是map的一种实现方案</strong>。<strong>不要将map与哈希表混为一谈，也不要单纯认为查找的时间复杂度一定就是O(1),还是要看具体实现</strong>。</p><p>【实现】：哈希表的底层实现就是一个数组。它先把这个 <code>key</code> 通过一个哈希函数转化成数组里面的索引，然后增删查改操作和数组基本相同。数据结构中是这样描述的</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>I</mi><mi>n</mi><mi>d</mi><mi>e</mi><mi>x</mi><mo>=</mo><mi>H</mi><mi>a</mi><mi>s</mi><mi>h</mi><mo stretchy="false">(</mo><mi>K</mi><mi>e</mi><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">Index = Hash(Key)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal">n</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">a</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">Key</span><span class="mclose">)</span></span></span></span></span></p><p>为什么key是唯一的，但是value可以不唯一？因为哈希表通过<strong>哈希函数</strong>把 key 转化成 table 中的<strong>合法索引</strong>，才能实现时间复杂度为O(1)的查找，如果同一个键有多个，那么求出来的同一个索引就有多个，就会发生冲突。<strong>哈希表的设计核心在于设计哈希函数</strong>，其他的操作都是依赖于哈希函数实现的，哈希函数的复杂度有多高，其他函数的复杂度就有多高。</p><p>在数据结构中，常见的哈希函数是：取余法、随机数法、平方取中间位数等，最简单、常用的就是取余法</p><hr><p><strong>负载因子</strong></p><p>【概念】：负载因子是一个哈希表装满的程度的度量。一般来说，负载因子越大，说明哈希表里面存储的键值对越多，哈希冲突的概率就越大，哈希表的操作性能就越差。<strong>如果我们需要自己设计一个哈希函数，就需要考虑到在负载因子增大的时候扩容</strong>，防止冲突的概率变大。</p><p><strong>键值对的注意事项</strong></p><p>【建议或者强制】：<strong>键应该是不可变数据类型</strong>，比如Java中的Integer和String，否则对键值的修改会导致映射的索引变化，甚至会导致键值对丢失的问题。</p><h4 id="哈希冲突的解决方法">哈希冲突的解决方法</h4><p><strong>线性探测法</strong></p><p>一旦多个键值对哈希冲突并使用线性探测法时，它们的索引关系就是“连续的”。比如</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">//代码部分</span><br><span class="line">put(0, a)</span><br><span class="line">put(10, b)</span><br><span class="line">put(20, c)</span><br><span class="line"></span><br><span class="line">put(3, A)</span><br><span class="line">put(13, B)</span><br><span class="line"></span><br><span class="line">put(30, d)</span><br><span class="line">put(40, e)</span><br><span class="line"></span><br><span class="line">//示意图</span><br><span class="line"></span><br><span class="line">table = [a, b, c, A, B, d, e, _, _, _]</span><br><span class="line">index    0  1  2  3  4  5  6  7  8  9</span><br><span class="line">hash     ^        ^</span><br><span class="line">key      0 10 20  3 13  30 40</span><br></pre></td></tr></table></figure><p>这里a、b、c都是在<strong>索引0处哈希冲突并使用线性探测法匹配到自己的索引</strong>，分别是0，1，2,如果我们将b的键值对删除，那么就会导致a与c之间存在<code>nullptr</code>，而<code>get</code>函数的逻辑是一旦遇到<code>nullptr</code>就会停止并返回-1，就会导致明明存在但无法找到的情况，所以<strong>必须保证连续性</strong></p><p>后续labuladong的部分内容需要会员才能看，到时候在淘宝上买一个。</p><h3 id="树">树</h3><h4 id="二叉树">二叉树</h4><p>最重要的数据结构之一，是理解树相关的算法和图相关算法的基础和前提。</p><p>【概念】：中文的概念这里不再赘述，需要注意的是在英文中<code>Complete Binary Tree</code>对应的是完全二叉树，而<code> Perfect Binary Tree。</code>对应的是满二叉树。<code>Full Binary Tree</code>是指一棵二叉树的所有节点要么没有孩子节点，要么有两个孩子节点，如果英语直译的话很容易翻译成满二叉树，而实际上不是。</p><hr><p><strong>二叉树的遍历</strong></p><ol><li>不管学校里教的，刷题刷的，还是算法导论里面写的，核心就一句话。<strong>递归遍历节点的顺序仅取决于左右子节点的递归调用顺序，与其他代码无关</strong>。也就是以下代码</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">traverse</span><span class="params">(TreeNode* root)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (root == <span class="literal">nullptr</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line">    <span class="comment">//这两个左右子节点递归调用的顺序决定了遍历节点的顺序，与什么printf函数均无关</span></span><br><span class="line"><span class="built_in">traverse</span>(root-&gt;left);</span><br><span class="line"><span class="built_in">traverse</span>(root-&gt;right);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>学过数据结构的读者会认为遍历顺序不是有前中后序和层序遍历吗？是的，不过我们的输出函数是穿插在这两个节点调用函数中的，当然会有不同的效果，如下<a href="https://leetcode.cn/problems/binary-tree-preorder-traversal/">力扣题目</a></li></ol><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Definition for a binary tree node.</span></span><br><span class="line"><span class="comment"> * public class TreeNode &#123;</span></span><br><span class="line"><span class="comment"> *     int val;</span></span><br><span class="line"><span class="comment"> *     TreeNode left;</span></span><br><span class="line"><span class="comment"> *     TreeNode right;</span></span><br><span class="line"><span class="comment"> *     TreeNode() &#123;&#125;</span></span><br><span class="line"><span class="comment"> *     TreeNode(int val) &#123; this.val = val; &#125;</span></span><br><span class="line"><span class="comment"> *     TreeNode(int val, TreeNode left, TreeNode right) &#123;</span></span><br><span class="line"><span class="comment"> *         this.val = val;</span></span><br><span class="line"><span class="comment"> *         this.left = left;</span></span><br><span class="line"><span class="comment"> *         this.right = right;</span></span><br><span class="line"><span class="comment"> *     &#125;</span></span><br><span class="line"><span class="comment"> * &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> List&lt;Integer&gt; <span class="title function_">preorderTraversal</span><span class="params">(TreeNode root)</span> &#123;</span><br><span class="line">        traverse(root);</span><br><span class="line">        <span class="keyword">return</span> res;</span><br><span class="line">       </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//结果数组</span></span><br><span class="line">    LinkedList&lt;Integer&gt; res = <span class="keyword">new</span> <span class="title class_">LinkedList</span>&lt;Integer&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="comment">//遍历函数</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">traverse</span><span class="params">(TreeNode root)</span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(root == <span class="literal">null</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//前序遍历</span></span><br><span class="line">        res.add(root.val);</span><br><span class="line">        traverse(root.left);</span><br><span class="line">        traverse(root.right);</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>还有一点要注意的是，在刷有关树的题目(使用Java语言)时有时候题目要求你返回List类型，注意Java中的List是接口，而实现这个接口的有LinkedList、ArrayList等，根据需要返回实际的类。</p><h4 id="多叉树">多叉树</h4><p>【数据结构】在leetcode中基本上和二叉树的结构一样，就只是类型变成了<code>vector</code> 用于存放节点的数组</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Node</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="type">int</span> val;</span><br><span class="line">    vector&lt;Node*&gt;children;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>【常见的算法】</p><ol><li>对于多叉树来说，前中后序遍历失去了意义，但是还有层序遍历可以实现，这也是多叉树常用的遍历算法，仅次于DFS与BFS。示例如下</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//N叉树的层序遍历</span></span><br><span class="line"><span class="comment">//方法1 借助队列</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">levelOrderTraverse1</span><span class="params">(Node* root)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">nullptr</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    std::queue&lt;Node*&gt; q;</span><br><span class="line">    q.<span class="built_in">push</span>(root);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (!q.<span class="built_in">empty</span>())</span><br><span class="line">    &#123;</span><br><span class="line">        Node* cur = q.<span class="built_in">front</span>();</span><br><span class="line">        q.<span class="built_in">pop</span>();</span><br><span class="line">        <span class="comment">//访问cur节点</span></span><br><span class="line">        std::cout &lt;&lt; cur-&gt;val &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//把cur所有子节点加入队列</span></span><br><span class="line">        <span class="keyword">for</span> (Node* child : cur-&gt;children)</span><br><span class="line">        &#123;</span><br><span class="line">            q.<span class="built_in">push</span>(child);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//方法2 记录节点深度</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">levelOrderTraverse</span><span class="params">(Node* root)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">nullptr</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    std::queue&lt;Node*&gt; q;</span><br><span class="line">    q.<span class="built_in">push</span>(root);</span><br><span class="line">    <span class="type">int</span> depth = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span> (!q.<span class="built_in">empty</span>())</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> sz = q.<span class="built_in">size</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; sz; i++)</span><br><span class="line">        &#123;</span><br><span class="line">            Node* cur = q.<span class="built_in">front</span>();</span><br><span class="line">            q.<span class="built_in">pop</span>();</span><br><span class="line"></span><br><span class="line">            <span class="comment">//访问cur节点，同时知道他所在的层数</span></span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;depth = &quot;</span> &lt;&lt; depth &lt;&lt; <span class="string">&quot;, val = &quot;</span> &lt;&lt; cur-&gt;val &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">for</span> (Node* child : cur-&gt;children)</span><br><span class="line">            &#123;</span><br><span class="line">                q.<span class="built_in">push</span>(child);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//方法3 记录权重</span></span><br><span class="line"><span class="comment">//带权重的树节点</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">State</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    Node* node;</span><br><span class="line">    <span class="type">int</span> depth;</span><br><span class="line"></span><br><span class="line">    <span class="built_in">State</span>(Node* node, <span class="type">int</span> dept) :<span class="built_in">node</span>(node), <span class="built_in">depth</span>(depth) &#123;&#125;;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">levelOrderTraverse3</span><span class="params">(Node* root)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (root == <span class="literal">nullptr</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    std::queue&lt;State&gt;q;</span><br><span class="line">    q.<span class="built_in">push</span>(<span class="built_in">State</span>(root,<span class="number">1</span>));</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (!q.<span class="built_in">empty</span>())</span><br><span class="line">    &#123;</span><br><span class="line">        State state = q.<span class="built_in">front</span>();</span><br><span class="line">        q.<span class="built_in">pop</span>();</span><br><span class="line"></span><br><span class="line">        Node* cur = state.node;</span><br><span class="line">        <span class="type">int</span> depth = state.depth;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//访问节点</span></span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;depth = &quot;</span> &lt;&lt; depth &lt;&lt; <span class="string">&quot;, val = &quot;</span> &lt;&lt; cur-&gt;val &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//进入子节点，注意深度+1</span></span><br><span class="line">        <span class="keyword">for</span> (Node* child : cur-&gt;children)</span><br><span class="line">        &#123;</span><br><span class="line">            q.<span class="built_in">push</span>(<span class="built_in">State</span>(child,depth<span class="number">+1</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h4 id="字典树-也叫前缀树">字典树(也叫前缀树)</h4><p>【数据结构】：和多叉树一样，不同的是一般用<strong>孩子数组的索引代表一个字符</strong>。的值.示例代码如下。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> V&gt;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">TrieNode</span></span><br><span class="line">&#123;</span><br><span class="line">V val = <span class="literal">NULL</span>;<span class="comment">//val是键所对应的值</span></span><br><span class="line">TRieNode&lt;v&gt;* children[<span class="number">256</span>] = &#123; <span class="literal">NULL</span> &#125;;<span class="comment">//这里索引代表键中的一个字符，可以避免重复存储相同的前缀和</span></span><br><span class="line"><span class="comment">//这也是字典树被称为前缀树的原因</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>其中白色节点代表 <code>val</code> 字段为空，橙色节点代表 <code>val</code> 字段非空。用<strong>树枝(也就是连线)表示字符</strong>。这样就能共享前缀，从而减少大量的存储空间消耗</p><p>如果读者对数据结构足够了解的话，会发现和霍夫曼树有几分相似之处。没错，霍夫曼树差不多是相反的，是避免一个二进制串是另一个二进制串的前缀。</p><h4 id="二叉堆">二叉堆</h4><p>【数据结构】：本质是二叉树，其中优先级队列可以用数组的存储结构实现，示例如下.</p><p>注意优先级队列本质是树，对于任何一个节点，都大于(或者小于)其子节点。每次插入或者删除都会自动调整树的结构。使其保持二叉堆的特性。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;functional&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdexcept&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">//优先级队列的实现-用数组的存储结构，和树的逻辑结构实现</span></span><br><span class="line"><span class="comment">//前提是完全二叉树，因为完全二叉树元素是连续的，可以用数组连续的排放</span></span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyPriorityQueue</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line"><span class="comment">//堆数组</span></span><br><span class="line">std::vector&lt;T&gt;heap;</span><br><span class="line"></span><br><span class="line"><span class="comment">//堆中元素的数量</span></span><br><span class="line"><span class="type">int</span> size;</span><br><span class="line"></span><br><span class="line"><span class="comment">//元素比较器</span></span><br><span class="line">std::function&lt;<span class="type">bool</span>(<span class="type">const</span> T&amp;, <span class="type">const</span> T&amp;)&gt; comparator;</span><br><span class="line"></span><br><span class="line"><span class="comment">//父节点的索引</span></span><br><span class="line"><span class="comment">//规律和二叉树的一样，这里索引从0开始</span></span><br><span class="line"><span class="comment">//自己列一个数组然后推理就行，和数据结构中左右孩子节点求法还是不一样的</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">parent</span><span class="params">(<span class="type">int</span> node)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> (node - <span class="number">1</span>) / <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//左孩子节点的索引</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">left</span><span class="params">(<span class="type">int</span> node)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> node * <span class="number">2</span> + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//右孩子节点的索引</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">right</span><span class="params">(<span class="type">int</span> node)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> node * <span class="number">2</span> + <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//交换数组的两个元素</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swap</span><span class="params">(<span class="type">int</span> i, <span class="type">int</span> j)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">std::<span class="built_in">swap</span>(heap[i], heap[j]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//调整堆的大小</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">resize</span><span class="params">(<span class="type">int</span> capacity)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (capacity &gt; size)</span><br><span class="line">&#123;</span><br><span class="line">heap.<span class="built_in">resize</span>(capacity);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//上浮操作，时间复杂度是树高O(logn)</span></span><br><span class="line"><span class="comment">//持续追踪一个节点，直到其上浮到合适的位置</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">swim</span><span class="params">(<span class="type">int</span> node)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//如果节点比父节点值要小</span></span><br><span class="line"><span class="keyword">while</span> (node &gt; <span class="number">0</span> &amp;&amp; <span class="built_in">comparator</span>(heap[<span class="built_in">parent</span>(node)], heap[node]))</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">swap</span>(<span class="built_in">parent</span>(node), node);</span><br><span class="line">node = <span class="built_in">parent</span>(node);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//下沉操作，时间复杂度为树高O(logN)</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">sink</span><span class="params">(<span class="type">int</span> node)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">while</span> (<span class="built_in">left</span>(node) &lt; size || <span class="built_in">right</span>(node) &lt; size)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//比较自己的左右子节点，找最小值</span></span><br><span class="line"><span class="type">int</span> min = node;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">left</span>(node) &lt; size &amp;&amp; <span class="built_in">comparator</span>(heap[min], heap[<span class="built_in">left</span>(node)]))</span><br><span class="line">&#123;</span><br><span class="line">min = <span class="built_in">left</span>(node);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">right</span>(node) &lt; size &amp;&amp; <span class="built_in">comparator</span>(heap[min], heap[<span class="built_in">right</span>(node)]))</span><br><span class="line">&#123;</span><br><span class="line">min = <span class="built_in">right</span>(node);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//如果当前节点比子节点都小</span></span><br><span class="line"><span class="keyword">if</span> (min == node)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//与最小值交换</span></span><br><span class="line"><span class="built_in">swap</span>(node, min);</span><br><span class="line"><span class="comment">//继续下沉</span></span><br><span class="line">node = min;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"><span class="comment">//构造函数</span></span><br><span class="line"><span class="built_in">MyPriorityQueue</span>(<span class="type">int</span> capacity, std::function&lt;<span class="built_in">bool</span>(<span class="type">const</span> T&amp;, <span class="type">const</span> T&amp;)&gt;compator)</span><br><span class="line">:<span class="built_in">heap</span>(capacity), <span class="built_in">size</span>(<span class="number">0</span>), <span class="built_in">comparator</span>(std::<span class="built_in">move</span>(compator)) &#123;&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回堆的大小</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">getSize</span><span class="params">()</span> <span class="type">const</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> size;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//判断堆是否为空</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">isEmpty</span><span class="params">()</span> <span class="type">const</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> size == <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//查找元素,返回堆顶的元素，其时间复杂度是O(1)</span></span><br><span class="line"><span class="function"><span class="type">const</span> T&amp; <span class="title">peek</span><span class="params">()</span> <span class="type">const</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">isEmpty</span>())</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">throw</span> std::<span class="built_in">underflow_error</span>(<span class="string">&quot;Priority queue underflow&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> heap[<span class="number">0</span>];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//向堆中插入一个元素，时间复杂度为O(logN)</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">push</span><span class="params">(<span class="type">const</span> T&amp; x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//扩容</span></span><br><span class="line"><span class="keyword">if</span> (size == heap.<span class="built_in">size</span>())</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">resize</span>(<span class="number">2</span> * heap.<span class="built_in">size</span>());</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//把新元素追加到最后</span></span><br><span class="line">heap[size] = x;</span><br><span class="line"><span class="comment">//然后上浮,传入的参数为数组的索引</span></span><br><span class="line"><span class="built_in">swim</span>(size);</span><br><span class="line">size++;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//删除堆顶元素，时间复杂度为O(logN)</span></span><br><span class="line"><span class="function">T <span class="title">pop</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">isEmpty</span>())</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">throw</span> std::<span class="built_in">underflow_error</span>(<span class="string">&quot;PriorityQueue underflow&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">T res = heap[<span class="number">0</span>];</span><br><span class="line"><span class="comment">//把堆底元素放在堆顶</span></span><br><span class="line"><span class="built_in">swap</span>(<span class="number">0</span>, size - <span class="number">1</span>);</span><br><span class="line">size--;</span><br><span class="line"><span class="comment">//然后下沉到正确的位置</span></span><br><span class="line"><span class="built_in">sink</span>(<span class="number">0</span>);</span><br><span class="line"><span class="comment">//缩容</span></span><br><span class="line"><span class="keyword">if</span> (size &gt; <span class="number">0</span> &amp;&amp; size == heap.<span class="built_in">size</span>() / <span class="number">4</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">resize</span>(heap.<span class="built_in">size</span>() / <span class="number">2</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_PriorityQueue</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">// 使用lambda表达式来传递比较器</span></span><br><span class="line"><span class="comment">// 小顶堆</span></span><br><span class="line"><span class="function">MyPriorityQueue&lt;<span class="type">int</span>&gt; <span class="title">pq</span><span class="params">(<span class="number">3</span>, [](<span class="type">const</span> <span class="type">int</span>&amp; a, <span class="type">const</span> <span class="type">int</span>&amp; b) &#123; <span class="keyword">return</span> a &gt; b; &#125;)</span></span>;</span><br><span class="line">pq.<span class="built_in">push</span>(<span class="number">3</span>);</span><br><span class="line">pq.<span class="built_in">push</span>(<span class="number">1</span>);</span><br><span class="line">pq.<span class="built_in">push</span>(<span class="number">4</span>);</span><br><span class="line">pq.<span class="built_in">push</span>(<span class="number">1</span>);</span><br><span class="line">pq.<span class="built_in">push</span>(<span class="number">5</span>);</span><br><span class="line">pq.<span class="built_in">push</span>(<span class="number">9</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1 1 3 4 5 9</span></span><br><span class="line"><span class="keyword">while</span> (!pq.<span class="built_in">isEmpty</span>()) &#123;</span><br><span class="line">std::cout &lt;&lt; pq.<span class="built_in">pop</span>() &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line">std::cout &lt;&lt; std::endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>线段树</strong></p><p>【数据结构】：其特点是叶子节点是区间上具体一点的值，而<strong>从根节点到非叶子节点都是区间的二分</strong>。比如根节点是[0,11],其左右孩子分别是[0,5],[6,11]，相应的左右孩子又分别是[0,2],[3,5],[6,8],[8,11],也就是<code>[left,mid],[mid,right]，其中mid = (left+right)/2</code> 向下取整。这里的<strong>非叶子节点相当于索引</strong>，用于快速计算出区间的和等。</p><h3 id="排序">排序</h3><h4 id="选择排序">选择排序</h4><p>如果你学过排序，请忘掉你背过的代码，作为一个没有学过编程的学生去想，对于一组数据，如何从小到大排序。</p><p>你的第一反应就是穷举，也就是每次从未排序的集合中找出最小的放在前面，然后再对剩下的重复此操作。这就是选择排序</p><p>示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">//选择排序的实现</span></span><br><span class="line"><span class="comment">//时间复杂度为O(n^2)</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">sort</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp; nums)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n = nums.<span class="built_in">size</span>();</span><br><span class="line"><span class="comment">//其中sortedIndex是一个分割线</span></span><br><span class="line"><span class="comment">//索引 &lt; sortedIndex的元素都是已经排序后的</span></span><br><span class="line"><span class="comment">//索引 &gt;= sortedIndex的元素都是未排序的</span></span><br><span class="line"><span class="type">int</span> sortedIndex = <span class="number">0</span>;<span class="comment">//初始化为所有元素都没有排序</span></span><br><span class="line"><span class="keyword">while</span> (sortedIndex &lt; n)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//先找到[sortedIndex,n)中的最小值</span></span><br><span class="line"><span class="type">int</span> minIndex = sortedIndex;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = sortedIndex + <span class="number">1</span>; i &lt; n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (nums[i] &lt; nums[minIndex])</span><br><span class="line">&#123;</span><br><span class="line">minIndex = i;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//交换最小值和sortedIndex处的元素</span></span><br><span class="line"><span class="type">int</span> temp = nums[sortedIndex];</span><br><span class="line">nums[sortedIndex] = nums[minIndex];</span><br><span class="line">nums[minIndex] = temp;</span><br><span class="line"></span><br><span class="line">sortedIndex++;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p><strong>选择排序的优化</strong></p><p>优化的重点是不稳定的排序，核心在于交换后元素之间的相对顺序改变了——比如2 2`本来2` 应该在2的后面(后一位两位都行，如果要求在确定的一位就是绝对顺序)，但是选择排序交换之后就变成2` 2 这样，就破坏了相对顺序。解决问题的关键在于不要将确定后的最小值交换回去。而是用数组中间插入元素的思路，给sortedIndex索引后一位留空，等待下一个最小值填充。</p><h4 id="希尔排序">希尔排序</h4><p>以下是leetcode的题目，用希尔排序，采用<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><msup><mn>3</mn><mi>k</mi></msup><mo>−</mo><mn>1</mn></mrow><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex">\frac{3^k-1}{2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.3879em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0429em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">3</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.927em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> 的递增函数实现</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span>[] sortArray(<span class="type">int</span>[] nums) &#123;</span><br><span class="line">        <span class="comment">//1. 先用递增函数找出适合该数组的最大步长</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">n</span> <span class="operator">=</span> nums.length;</span><br><span class="line">        <span class="type">int</span> <span class="variable">h</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">while</span>(h&lt;n/<span class="number">3</span>)&#123;</span><br><span class="line">            h = h*<span class="number">3</span>+<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.然后按递增函数的每一个步长依次插入排序并逐渐缩小步长</span></span><br><span class="line">        <span class="keyword">while</span>(h&gt;=<span class="number">1</span>)&#123;</span><br><span class="line">            <span class="type">int</span> <span class="variable">sortedIndex</span> <span class="operator">=</span> h;</span><br><span class="line">            <span class="keyword">while</span>(sortedIndex&lt;n)&#123;</span><br><span class="line">                <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> sortedIndex;i&gt;=h;i-=h)&#123;</span><br><span class="line">                    <span class="comment">//3. 如果后面的值小于前面的</span></span><br><span class="line">                    <span class="keyword">if</span>(nums[i]&lt;nums[i-h])&#123;</span><br><span class="line">                        <span class="comment">//交换</span></span><br><span class="line">                        <span class="type">int</span> <span class="variable">temp</span> <span class="operator">=</span> nums[i-h];</span><br><span class="line">                        nums[i-h] = nums[i];</span><br><span class="line">                        nums[i] = temp;</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">else</span>&#123;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//找下一个数组</span></span><br><span class="line">                sortedIndex++;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//缩短步长</span></span><br><span class="line">            h/=<span class="number">3</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> nums;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>常见的算法刷题框架</h1><p><strong>有几句话我要写在这里，对于算法的理解非常贴切</strong>。均来自labuladong的算法笔记，在未来的刷题过程中会深刻体会到这些道理。</p><div class="note info default simple"><p>种种数据结构，皆为<strong>数组</strong>（顺序存储）和<strong>链表</strong>（链式存储）的变换。</p><p>数据结构的关键点在于<strong>遍历和访问</strong>，即<strong>增删查改</strong>等基本操作。</p><p>种种算法，皆为<strong>穷举</strong>。</p><p>穷举的关键点在于<strong>无遗漏和无冗余</strong>。熟练掌握算法框架，可以做到无遗漏；充分利用信息，可以做到无冗余。</p></div><hr><h3 id="双指针">双指针</h3><ol><li>【推荐】在链表中建议<strong>使用虚拟头节点</strong>技巧，可以规避额外处理的情况(比如空指针，越界的情况)</li></ol><p><strong>正例：</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> ListNode <span class="title function_">mergeTwoLists</span><span class="params">(ListNode l1, ListNode l2)</span> &#123;</span><br><span class="line">        <span class="comment">// 虚拟头结点</span></span><br><span class="line">        <span class="type">ListNode</span> <span class="variable">dummy</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ListNode</span>(-<span class="number">1</span>), p = dummy;</span><br><span class="line">        <span class="type">ListNode</span> <span class="variable">p1</span> <span class="operator">=</span> l1, p2 = l2;</span><br><span class="line"></span><br><span class="line">       <span class="comment">//合并链表实现</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//返回不带虚拟头结点的链表</span></span><br><span class="line">        <span class="keyword">return</span> dummy.next;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>【总结】：双指针只是一种形式，以不同的方式移动它就可以达到不同的效果，比如一个指针总是指向极值，另一个指针指向容器，就可以按<strong>顺序排列</strong>元素，或者分离，或者合并；一个指针快，一个指针慢，如果在”环“(无论是逻辑上的还是物理上的)上移动，就可以<strong>相遇</strong>；如果有条件的移动，就可以<strong>窗口</strong>一样筛选；是从一边移动？还是中心开花？还是从两侧向中间靠拢？都是可以研究的对象。关键在于<strong>移动的条件是什么？从哪里移动？是先操作再移动？</strong></li></ol><h3 id="二分查找">二分查找</h3><blockquote><p>一句话概括：<strong>思路很简单，细节是魔鬼</strong>。</p></blockquote><p>【实现】：常见的框架如下所示</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">binarySearch</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp; nums, <span class="type">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> left = <span class="number">0</span>, right = nums.<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (...) &#123;<span class="comment">//这里写终止二分搜索的判断语句</span></span><br><span class="line">        <span class="type">int</span> mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span> (nums[mid] == target) &#123;</span><br><span class="line">            ...<span class="comment">//一般搜索到到目标函数就直接返回，不过要视题目而定</span></span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] &lt; target) &#123;</span><br><span class="line">            left = ...<span class="comment">//左指针如何移动</span></span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] &gt; target) &#123;</span><br><span class="line">            right = ...<span class="comment">//右指针如何移动</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>需要说明的是，在数据结构中mid是这样计算的</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> mid = (left+right)/<span class="number">2</span>;</span><br></pre></td></tr></table></figure><p>而在实际的算法题中，计算 <code>mid</code> 时需要防止溢出，代码中 <code>left + (right - left) / 2</code> 就可以防止left和right太大导致溢出的情况。</p><p>推理如右:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi>a</mi><mo>+</mo><mi>b</mi></mrow><mn>2</mn></mfrac><mo>=</mo><mfrac><mrow><mi>b</mi><mo>−</mo><mi>a</mi><mo>+</mo><mn>2</mn><mo>×</mo><mi>a</mi></mrow><mn>2</mn></mfrac><mo>=</mo><mi>a</mi><mo>+</mo><mfrac><mrow><mi>b</mi><mo>−</mo><mi>a</mi></mrow><mn>2</mn></mfrac></mrow><annotation encoding="application/x-tex">\frac{a+b}{2} = \frac{b-a+2 \times a}{2} = a+\frac{b-a}{2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2251em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mbin mtight">+</span><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2251em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">a</span><span class="mbin mtight">+</span><span class="mord mtight">2</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight">a</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2251em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">a</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p><strong>while中的判断一般有两种常见的形式</strong>：<code>left&lt;right</code> 和<code>left&lt;=right</code></p><p>区别在于你初始化的right是什么，比如你初始化为<code>int right = nums.size();</code> 本身right超出了数组索引的边界，相当于是<code>[left,right)</code> 左闭右开区间，当left = right时，此时[left,left)  而left&lt;right的终止条件是<code>left == right</code>.可以正确终止;left&lt;=right同理</p><p>left和right“指针”的<strong>修改</strong>:</p><p>在while判断条件下<code>left&lt;right</code> ，为什么是right = mid？同理，因为搜索区间是左闭右开，当mid被检测之后，下一步应该去mid的左侧或者右侧区间搜索，即<code>[left,mid)</code> 和<code>[mid+1,right)</code>  所以mid可以==right,left可以为mid+1;</p><p>以下是labuladong提供的二分查找的<strong>左右闭合区间</strong>的框架。<strong>如果 <code>target</code> 不存在，搜索左侧边界的二分搜索返回的索引是大于 <code>target</code> 的最小索引</strong>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">left_bound</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp; nums, <span class="type">int</span> target)</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> left = <span class="number">0</span>, right = nums.<span class="built_in">size</span>() - <span class="number">1</span>;</span><br><span class="line">    <span class="comment">// 搜索区间为 [left, right]</span></span><br><span class="line">    <span class="keyword">while</span> (left &lt;= right) &#123;<span class="comment">//终止条件是left == right+1</span></span><br><span class="line">        <span class="type">int</span> mid = left + (right - left) / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">if</span> (nums[mid] &lt; target) &#123;</span><br><span class="line">            <span class="comment">// 搜索区间变为 [mid+1, right]</span></span><br><span class="line">            left = mid + <span class="number">1</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] &gt; target) &#123;</span><br><span class="line">            <span class="comment">// 搜索区间变为 [left, mid-1]</span></span><br><span class="line">            right = mid - <span class="number">1</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (nums[mid] == target) &#123;</span><br><span class="line">            <span class="comment">// 收缩右侧边界</span></span><br><span class="line">            right = mid - <span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 判断 target 是否存在于 nums 中</span></span><br><span class="line">    <span class="comment">// 如果越界，target 肯定不存在，返回 -1</span></span><br><span class="line">    <span class="keyword">if</span> (left &lt; <span class="number">0</span> || left &gt;= nums.<span class="built_in">size</span>()) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 判断一下 nums[left] 是不是 target</span></span><br><span class="line">    <span class="keyword">return</span> nums[left] == target ? left : <span class="number">-1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h3 id="动态规划">动态规划</h3><p>【三要素】：<strong>重叠子问题、最优子结构、状态转移方程</strong>，在后续的解题中都是围绕这些展开的</p><p>来自labuladong的框架。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 自顶向下递归的动态规划</span></span><br><span class="line"><span class="comment"># 定义了一个方程</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">dp</span>(<span class="params">状态<span class="number">1</span>, 状态<span class="number">2</span>, ...</span>):</span><br><span class="line">    <span class="keyword">for</span> 选择 <span class="keyword">in</span> 所有可能的选择:</span><br><span class="line">        <span class="comment"># 此时的状态已经因为做了选择而改变</span></span><br><span class="line">        result = 求最值(result, dp(状态<span class="number">1</span>, 状态<span class="number">2</span>, ...))</span><br><span class="line">    <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line"><span class="comment"># 自底向上迭代的动态规划</span></span><br><span class="line"><span class="comment"># 初始化 base case</span></span><br><span class="line">dp[<span class="number">0</span>][<span class="number">0</span>][...] = base <span class="keyword">case</span></span><br><span class="line"><span class="comment"># 进行状态转移</span></span><br><span class="line"><span class="keyword">for</span> 状态<span class="number">1</span> <span class="keyword">in</span> 状态<span class="number">1</span>的所有取值：</span><br><span class="line">    <span class="keyword">for</span> 状态<span class="number">2</span> <span class="keyword">in</span> 状态<span class="number">2</span>的所有取值：</span><br><span class="line">        <span class="keyword">for</span> ...</span><br><span class="line">            dp[状态<span class="number">1</span>][状态<span class="number">2</span>][...] = 求最值(选择<span class="number">1</span>，选择<span class="number">2.</span>..)</span><br></pre></td></tr></table></figure><p>如何理解<strong>重叠子问题</strong>？以最经典的斐波那契数列为例，常见的暴力算法如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">fib</span><span class="params">(<span class="type">int</span> N)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (N == <span class="number">1</span> || N == <span class="number">2</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">fib</span>(N - <span class="number">1</span>) + <span class="built_in">fib</span>(N - <span class="number">2</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其时间复杂度为子问题 * 一个子问题所需要的时间，用递归树理解就是树中有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">2^{n}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span></span> 个节点，每一个节点的时间复杂度为O(1),两者相乘为<strong>指数级别</strong>的时间复杂度。为什么会这样呢？就是因为树中存在大量重复计算，比如求f(5)，f(5)的子问题是f(4)与f(3)，f(4)的子问题是f(3)与f(2),其中f(3)被重复计算了两次，如果树更高，重复计算的次数只会更多，这就是<strong>重复的子问题</strong>。</p><p>而对于这种重复的子问题，一种常见的解决思路是<strong>备忘录</strong>，也就是将计算过的结果记录下来，下次计算前如果发现备忘录中已经有了，就不需要重复递归计算了，示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">fib</span><span class="params">(<span class="type">int</span> n)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//备忘录初始化为0</span></span><br><span class="line">        <span class="function">vector&lt;<span class="type">int</span>&gt; <span class="title">memo</span><span class="params">(N<span class="number">+1</span>,<span class="number">0</span>)</span></span>;</span><br><span class="line">        <span class="comment">//带备忘录的递归</span></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">dp</span>(memo,N);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//带备忘录递归</span></span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">dp</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp;memo,<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(n == <span class="number">0</span> || n == <span class="number">1</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">return</span> n;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(memo[n]!=<span class="number">0</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">return</span> memo[n];</span><br><span class="line">        &#125;</span><br><span class="line">        memo = <span class="built_in">dp</span>(memo,n<span class="number">-1</span>)+<span class="built_in">dp</span>(memo,n<span class="number">-2</span>);</span><br><span class="line">        <span class="keyword">return</span> memo[n];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>通过备忘录将递归树剪枝，大大减少了冗余计算，示例图如下，来自labuladong的网站</p><p>由此可以看出，递归的思路一般是自顶向下，而动态规划恰恰相反，是从最简单的问题开始，一步步向上推，所以你会看到几乎大部分的动态规划都是借助<strong>循环遍历</strong>实现的。</p><p><strong>递归的思路反过来就是动态规划</strong>，示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">fib</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(n == <span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//创建一个备忘录数组</span></span><br><span class="line">    <span class="function">vector&lt;<span class="type">int</span>&gt; <span class="title">dp</span><span class="params">(n<span class="number">+1</span>)</span></span>;</span><br><span class="line">    dp[<span class="number">0</span>] = <span class="number">0</span>,dp[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line">    <span class="comment">//开始状态转移，也就是自底向上</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=n;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        dp[i] = dp[i<span class="number">-1</span>]+dp[i<span class="number">-2</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> dp[n];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p><strong>什么是状态转移方程</strong>？其实就是描述问题的函数，一般是分段函数，如下</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>n</mi><mo>=</mo><mn>1</mn><mo separator="true">,</mo><mn>2</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>+</mo><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>2</mn><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>n</mi><mo>&gt;</mo><mn>2</mn></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">f(n) = \begin{cases}1 &amp; n = 1,2 \\f(n-1)+f(n-2)&amp; n&gt;2 \end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">2</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>把参数 <code>n</code> 当做一个状态，这个状态 <code>n</code> 是由状态 <code>n - 1</code> 和状态 <code>n - 2</code> 转移（相加）而来，这就叫状态转移。</p><p><strong>状态转移方程往往是动态规划最关键的一步</strong>，其他什么备忘录等只是在此基础上进行优化而已。</p><hr><p>在上述代码的基础上，我们发现n状态只与n-1和n-2有关，那么就可以想到可以只保留n-1与n-2而不需要那么多的空间，只要记得每次刷新就行，最终得到的斐波那契的动态规划如下.如果在实际情况下发现只需要DP table中的一部分，就可以尝试缩小其大小</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">fib</span><span class="params">(<span class="type">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (n == <span class="number">0</span> || n == <span class="number">1</span>) &#123;</span><br><span class="line">        <span class="comment">// base case</span></span><br><span class="line">        <span class="keyword">return</span> n;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 分别代表 dp[i - 1] 和 dp[i - 2]</span></span><br><span class="line">    <span class="type">int</span> dp_i_1 = <span class="number">1</span>, dp_i_2 = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        <span class="comment">// dp[i] = dp[i - 1] + dp[i - 2];</span></span><br><span class="line">        <span class="type">int</span> dp_i = dp_i_1 + dp_i_2;<span class="comment">//先记录得到的i状态</span></span><br><span class="line">        <span class="comment">// 滚动更新</span></span><br><span class="line">        dp_i_2 = dp_i_1;<span class="comment">//</span></span><br><span class="line">        dp_i_1 = dp_i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> dp_i_1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>什么叫<strong>最优子结构</strong>？专业来说就是<strong>子问题互相独立</strong>，简单来说有点像贪心，比如要总分要高就要每科都要考高分，而每个科目成绩相互独立，互不影响，就叫最优子结构。一旦破坏了这种关系(比如数学考的高，英语就低)，这种情况下就不能简单的认为只要每科高就能实现总分高了。</p><p>比如凑零钱问题，常见的实现代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">coinChange</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp; coins, <span class="type">int</span> amount)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 题目要求的最终结果是 dp(amount)</span></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">dp</span>(coins, amount);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="comment">// 定义：要凑出金额 n，至少要 dp(coins, n) 个硬币</span></span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">dp</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp; coins, <span class="type">int</span> amount)</span> </span>&#123;</span><br><span class="line">        <span class="comment">// base case</span></span><br><span class="line">        <span class="keyword">if</span> (amount == <span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">if</span> (amount &lt; <span class="number">0</span>) <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"></span><br><span class="line">        <span class="type">int</span> res = INT_MAX;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> coin : coins) &#123;</span><br><span class="line">            <span class="comment">// 计算子问题的结果</span></span><br><span class="line">            <span class="type">int</span> subProblem = <span class="built_in">dp</span>(coins, amount - coin);</span><br><span class="line">            <span class="comment">// 子问题无解则跳过</span></span><br><span class="line">            <span class="keyword">if</span> (subProblem == <span class="number">-1</span>) <span class="keyword">continue</span>;</span><br><span class="line">            <span class="comment">// 在子问题中选择最优解，然后加一</span></span><br><span class="line">            res = <span class="built_in">min</span>(res, subProblem + <span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> res == INT_MAX ? <span class="number">-1</span> : res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>如果用labuladong给的递归树来解释的话，就是找到<strong>以金额amount为根节点，到某一个叶子节点值为0的点的最短路径(也就是从根到此叶子节点的深度-1)</strong>。建议<strong>一定要掌握画递归树</strong>，有助于理解<strong>动态规划的三要素</strong>。</p><p>反过来就是动态规划的代码了，示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="type">int</span> <span class="title">coinChange</span><span class="params">(vector&lt;<span class="type">int</span>&gt;&amp; coins, <span class="type">int</span> amount)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//dp[i]数组的定义是，凑出金额为i所需要的最少的硬币数量</span></span><br><span class="line">        <span class="comment">//将其每个值初始化为amount+1，因为凑出amount最多需要amount个1元，将其视作正无穷，防止溢出</span></span><br><span class="line">        vector&lt;<span class="type">int</span>&gt;<span class="built_in">dp</span>(amount<span class="number">+1</span>,amount<span class="number">+1</span>);</span><br><span class="line"></span><br><span class="line">        <span class="comment">//开始状态转移</span></span><br><span class="line">        <span class="comment">//dp数组第一位为0,实际根据题目改变</span></span><br><span class="line">        dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;dp.<span class="built_in">size</span>();i++)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="keyword">auto</span> coin:coins)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">//如果无解就跳过</span></span><br><span class="line">                <span class="keyword">if</span>(i-coin&lt;<span class="number">0</span>)</span><br><span class="line">                &#123;</span><br><span class="line">                    <span class="keyword">continue</span>;</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="comment">//状态转移方程</span></span><br><span class="line">                dp[i] = <span class="built_in">min</span>(dp[i],<span class="number">1</span>+dp[i-coin]);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">//返回参数前进行判断，是否值为amount+1</span></span><br><span class="line">        <span class="keyword">return</span> (dp[amount] == amount<span class="number">+1</span>)?<span class="number">-1</span>:dp[amount];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>状态转移方程简单来说就是：<strong>dp[i]依赖于<code>dp[i-1],dp[i-2]和dp[i-5]</code> ,从中选择最小的那个，然后+1(要选一个硬币才能达到dp[i])。</strong></p><h3 id="二叉树系列">二叉树系列</h3><ol><li><strong>快速排序就是个二叉树的前序遍历，归并排序就是个二叉树的后序遍历</strong></li><li><strong>所谓前序位置，就是刚进入一个节点（元素）的时候，后序位置就是即将离开一个节点（元素）的时候</strong> 比如前序遍历时在进入traverse()函数的时候就是刚进入一个元素，离开traverse(right)函数要结束就是即将离开一个节点的时候</li></ol><p>比如链表逆序打印，就是利用了递归的本质。<strong>先递归到链表尾部，在离开节点的时候再打印，也就是后序位置打印</strong>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 递归遍历单链表，倒序打印链表元素</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">traverse</span><span class="params">(ListNode* head)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (head == <span class="literal">nullptr</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">traverse</span>(head-&gt;next);</span><br><span class="line">    <span class="comment">// 后序位置</span></span><br><span class="line">    cout &lt;&lt; head-&gt;val &lt;&lt; endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>labuladong的图非常清晰，在数据结构中你也见到过，就是讲线索二叉树的时候画的<strong>进入和离开的线</strong>。</p><ol start="3"><li><strong>二叉树的所有问题，就是让你在前中后序位置注入巧妙的代码逻辑，去达到自己的目的，你只需要单独思考每一个节点应该做什么，其他的不用你管，抛给二叉树遍历框架，递归会在所有节点上做相同的操作</strong></li></ol><hr><div class="note info default simple"><p>动归/DFS/回溯算法都可以看做二叉树问题的扩展，只是它们的关注点不同：</p><ul><li>动态规划算法属于分解问题（分治）的思路，它的关注点在整棵「子树」。</li><li>回溯算法属于遍历的思路，它的关注点在节点间的「树枝」。</li><li>DFS 算法属于遍历的思路，它的关注点在单个「节点」。</li></ul></div><h3 id="贪心算法">贪心算法</h3><p>还记的之前的那个考试总分最高的例子吗？假设你参加高考，要考语数英物化生六门科目，其中每一门科目都有对应一系列的可选的分数，请输出一个序列，使得总分最高。</p><p>读者肯定能一眼看出答案，只要每个科目都选最高的，不就能使得总分最高了吗？这就是<strong>贪心的性质</strong>，能够通过局部最优解<strong>直接</strong>推导出全局最优解。</p><h2 id="参考">参考</h2><ol><li><a href="https://leetcode.cn/circle/discuss/E3yavq/">力扣刷题攻略</a>  读者可以在这里参考刷题。</li><li><a href="https://labuladong.online/algo/home/">本站简介 | labuladong 的算法笔记</a> 建议没有思路的读者按照此网站目录刷题</li></ol>]]></content>
    
    
    <summary type="html">主要参考各个刷算法的网站和资料学习相应的较为基础的算法题目,主要写一些个人的总结和思考内容,部分省略的地方会标明出处,旨在为后续实习和就业打下坚实的算法基础</summary>
    
    
    
    <category term="algorithm" scheme="https://lloydkai.cn/categories/algorithm/"/>
    
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="Leetcode" scheme="https://lloydkai.cn/tags/Leetcode/"/>
    
    <category term="Java" scheme="https://lloydkai.cn/tags/Java/"/>
    
  </entry>
  
  <entry>
    <title>算法系列(三)蓝桥杯_算法高阶(三)</title>
    <link href="https://lloydkai.cn/posts/lanqiaocup-series-five/"/>
    <id>https://lloydkai.cn/posts/lanqiaocup-series-five/</id>
    <published>2025-02-20T00:07:57.000Z</published>
    <updated>2026-04-23T01:45:29.272Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/rVx9ogHB31wf4mJ.jpg" alt></p><h1>算法高阶</h1><blockquote><p>本部分算法难度较高，建议读者充分掌握算法基础之后再来学习。个人感觉对于蓝桥杯有点多，但是对于leetcode刚刚好(¬‿¬)</p><p>目前以视频的方法为主，等蓝桥杯考完之后按照labuladong或者是考研的方法写代码。</p><p><strong>站主要备考考研了，可能要等考研之后才有充足的时间回头来修改和完善博客</strong></p></blockquote><h2 id="我的仓库使用指南">我的仓库使用指南</h2><p>我的仓库链接格式如下：<code>https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/1_20</code> 其中1_20表示的是日期(一般是2025)，里面的文件就包含对应题目的解答(均通过对应题目的测试)或者是算法实现，其中文件名<code>lanqiao</code>表示 是<strong>蓝桥杯官网上的题目</strong>，<code>_</code> 后面的数字是蓝桥杯的<strong>题目编号</strong>，可以找到对应的蓝桥杯的题目，比如题目链接是<code>https://www.lanqiao.cn/problems/498/learning/?page=1&amp;first_category_id=1&amp;problem_id=498</code>    <code>problems</code>斜杠后面的数字<strong>498</strong> 就是对应的题目编号，你就在我指定链接下面的文件夹下按照<code>lanqiao_题目编号.cpp</code> 这样的格式找对应文件，就可以看到对应题目的解答代码。</p><p><img src="https://s2.loli.net/2025/02/06/n4dH1aOXoCc35Sy.png" alt="001_demo.png"></p><hr><h2 id="数据结构">数据结构</h2><h3 id="基础数据结构">基础数据结构</h3><h4 id="RMQ问题">RMQ问题</h4><p>【概念】：RMQ(Range Minimum/Maximum Query)问题是指对于数组，<strong>每次给一个区间[l,r],要求返回区间内的最大值或最小值</strong>（的下标）也就是说，RMQ就是<strong>求区间最值的问题</strong>。对于RMQ问题，容易想到一种O(n)的方法，就是用i直接遍历区间，找出不断比较a[i]与max的大小关系，然后不断更新max,最后得出的就是最大值。但是如果要进行多次的查询，这个算法将会变得非常慢。于是，我们可以利用倍增和动态规划的思想，利用“ST表”这个数据结构来帮助解决。</p><p><strong>ST表</strong></p><p>ST表是一种可以“静态求区间最值”的数据结构，本质上是一种dp.假设我们要求区间最大值（最小值类似），设状态<code>st[i][j]</code>表示从开始，大小为2^ j的长度的区间的最大值，即区间[i,i+2^j-1]的最大值。状态转移方程为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>i</mi><mo>+</mo><mo stretchy="false">(</mo><mn>1</mn><mo>&lt;</mo><mo>&lt;</mo><mo stretchy="false">(</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">st[i][j]=max(st[i][j-1],st[i+(1&lt;&lt;(j-1))][j-1]);</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">))]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">])</span><span class="mpunct">;</span></span></span></span>注意状态转移的方向和保证区间合法。</p><p><strong>区间查询</strong>：为了查询区间[[l,r]的最大值，它可以分解为两个小区间的最大值，例如要求[2,7]的最大值，可以分解为[2,2+2 ^ 2-1],[7-2 ^ 2+1,7]的最大值，也就是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mn>2</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>2</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mn>7</mn><mo>−</mo><mn>4</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>2</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">max(st[2][2],st[7-4][2])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord">2</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">2</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord">7</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">4</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">2</span><span class="mclose">])</span></span></span></span>,拓展一下，[l,r]区间，需要找出一个k,使得2^ k&lt;=r-1+1,k&lt;=log2(r-l+1),可以分解为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>r</mi><mo>−</mo><msup><mn>2</mn><mi>k</mi></msup><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">max(st[l][k],st[r-2^k+1][k])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9324em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">])</span></span></span></span></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">getMax</span><span class="params">(<span class="type">int</span> l,<span class="type">int</span> r)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> k = <span class="built_in">log</span>(r-l<span class="number">+1</span>)/<span class="built_in">log</span>(<span class="number">2</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">max</span>(st[l][k],st[r-(l&lt;&lt;k)<span class="number">+1</span>][k]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1205/learning/?page=1&amp;first_category_id=1&amp;problem_id=1205">1.区间最大值 - 蓝桥云课</a></li></ul><p>直接按照st表模板套就行</p><h4 id="并查集">并查集</h4><p>【概念】：并查集是一种图形数据结构，用于存储图中结点的连通关系。每个结点有一个父亲，可以理解为“一只伸出去的手”，会指向另外一个点，初始时指向自己。个点的根节点是该点的父亲的父亲的…的父亲，直到某个点的父亲是自己（根）当两个点的根相同时，我们就说他们是属于同一类，或者说是连通的。比如：3、6的根都是3，所以他们是连通的，2、4是连通的，而2、6不连通，因为他们的根不同。</p><p>【实现】：找根函数</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">root</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//如果根是自己就返回</span></span><br><span class="line">    <span class="keyword">if</span>(pre[x] == x)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> x;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//根不是自己就返回父节点的根</span></span><br><span class="line">    <span class="comment">//pre数组是存储父节点的数组</span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">root</span>(pre[x]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>合并操作</strong>：在并查集中，所有的操作都在根上，假如我要使得x和y两个点合并，只需要将root(x)指向root(y),或使得root(y)指向root(x)。即</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pre[<span class="built_in">root</span>(x)] = <span class="built_in">root</span>(y);</span><br></pre></td></tr></table></figure><p><strong>路径压缩</strong>：找根函数的复杂度最坏情况下会达到O(n),如果查询次数较多的话效率将会非常低下。我们可以在找根的过程中，将父亲直接指向根，从而实现路径压缩，这样可以使得找根的总体时间,复杂度接近O(1)。如下图，执行一次root(7)之后，沿途的点都会直接指向根3。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">root</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> pre[x] = (pre[x] == x?x:<span class="built_in">root</span>(pre[x]));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1135/learning/?page=1&amp;first_category_id=1&amp;problem_id=1135">1.蓝桥幼儿园 - 蓝桥云课</a></li></ul><p>直接用并查集就行了</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_20">点击此处</a></p><hr><p><strong>带权并查集</strong></p><p>【例子引入】：某个镇上的几个居民家族怀着重建家谱的愿望，以便能够追溯自己的家族历史。由于时间的流逝，这些家族只能依靠现存的资料来确定镇上曾经存在过的家族关系。根据现有的资料，我们能够获知镇上居民之间的父子关系，从而描绘出一个家族谱系。基于上述情况，我们需要进行一系列的查询，以确定每个现存居民属于哪个家族，并且<strong>找出最早祖先的名字，并且查询是第几代人</strong>。这个过程将帮助我们重新构建这些家族的历史，从而理清各个家族之间的关系。此时就是<strong>带权并查集</strong>了，<strong>特殊的每个边权值为1</strong>。简而言之，就是带权值的并查集。</p><p>【实现】：带权并查集和普通的并查集不一样，需要维护某一个节点到其根节点的路径长度(权值和)，首先我们需要定义一个dis数组：dis[],fa[],由于我们还需要维护路径长度，所以需要改写两个操作函数：1. 因为路径压缩会改变点与点的连接关系，路径压缩后，点的父节点变为了根节点，所以需要更新Dis数组 2.集合的代表元（根节点）是没有父结点的，所以Dis数组中也没有值。但是合并集合后其中一个根节点变为了另一个集合根节点的子节点，所以需要赋值。</p><p><strong>Find函数：</strong><br>递推找到该节点的祖先节点，在回归过程中实现路径压缩。路径压缩可以理解成将该节点直接连到祖先节点上，当它儿子节点，同时权值dis也更新成与祖先节点的关系。路径上的每一个节点先更新该节点的父亲节点father(=fa[x])与祖先节点的关系（递归），然后该节点和祖先节点的关系就可以表示为dis[x]+dis[father];示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">find</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//如果节点的父节点是他本身</span></span><br><span class="line">    <span class="keyword">if</span>(f[x] == x)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> x;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//否则递归找到其父节点</span></span><br><span class="line">    <span class="type">int</span> fa = <span class="built_in">find</span>(f[x]);</span><br><span class="line">    dis[x] += dis[f[x]];</span><br><span class="line">    <span class="keyword">return</span> f[x] = fa;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>merge函数</strong>：合并两个没有联系的独立集合。两个集合本来没有联系，每个集合内部的点存在联系，通过联系两个不同集合中独立的两个点使得两个集合建立关系。合并两个集合，<strong>实质就是建立两个集合中祖先节点之间的关系</strong>。合并后集合内部的点之间的关系通过各自和祖先节点之间的关系得到。示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//思路：先通过find实现路径压缩，将x和y节点直接连在各自祖先节点上，得出和祖先节点的关系dis[x],dis[y],合并祖先节点fx,fy,并通过向量得到fx和fy关系。</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">merge</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y,<span class="type">int</span> c)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> fx = <span class="built_in">find</span>(x);</span><br><span class="line">    <span class="type">int</span> fy = <span class="built_in">find</span>(y);</span><br><span class="line">    <span class="comment">//如果两个节点的父节点相同</span></span><br><span class="line">    <span class="keyword">if</span>(fx == fy)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    f[fx] = fy;</span><br><span class="line">    dis[fx]+=c+dis[y]-dis[x];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>dist函数</strong>：判断两个节点是否存在关系，以及什么关系的函数。先find找各自祖先，如果重合，那么就是有关系，如果不重合，则无关，<br>返回-1.重合的情况下，二者已通过find路径压缩得到与共同祖先的关系，分别是dis[x],dis[y}。那么x和y之间的关系通过向量的关系可以得到dis[x]-dis[y]</p><p><strong>可撤销并查集</strong></p><p>后续补上，目前性价比较低。</p><h4 id="堆">堆</h4><p>【概念】：在语法基础课中其实有讲过优先队列，其实优先队列就是一个堆，它可以维护一个集合的最大值（或最小值）。</p><p>在做算法题的时候强调过会使用优先级队列就行了，如果想要深入理解数据结构，还需要<strong>手动实现堆这种数据结构</strong>。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3433/learning/?page=1&amp;first_category_id=1&amp;problem_id=3433">1.一道简单的取模问题 - 蓝桥云课</a></li></ul><p>优先级队列的经典应用，做题基本上达到这种程度就可以了，接下来就要讲解堆的实现。</p><hr><p><strong>堆是一种二叉树</strong>，对于每个结点满足：儿子的权值都比自己的权值小。这个性质不断向上传递直到根，就可以保证：<strong>根的权值是整棵树中最大的</strong>。例如左图是一个<strong>大根堆(或者叫大顶堆)</strong>，而右图却不是。</p><p>手写堆比较繁琐(<strong>学过数据结构的同学应该深有体会</strong>)，实际做题中几乎不用，但是对于我们理解堆这种数据结构尤为重要，手写堆需要实现以下几个函数：</p><ol><li><p>pushup()将某个点向上更新，一般是将最后一个点向上更新</p></li><li><p>pushdown()将某个点向下更新，一般将根向下更新</p></li><li><p>push()插入一个点到堆内</p></li><li><p>pop()将根结点删除</p></li></ol><p>我们采用数组的方式来存储数据，利用二叉树的性质：<strong>2x表示x的左儿子编号，2x+1表示x的右儿子编号。用sz表示结点数量，a[x]表示结点x的权值。</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//pushup函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pushup</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(x!=<span class="number">1</span>) <span class="comment">//只要不是根节点，就一直和父节点比较并更新</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(a[x]&gt;a[x&gt;&gt;<span class="number">1</span>])</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">swap</span>(a[x],a[x&gt;&gt;<span class="number">1</span>]);</span><br><span class="line">            x&gt;&gt;=<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">break</span>;<span class="comment">//如果节点到了某个位置停下了，就跳出</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//pushdown函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pushdown</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//如果没有子节点</span></span><br><span class="line">    <span class="keyword">if</span>((x&lt;&lt;<span class="number">1</span>)&gt;sz)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//如果只有左子节点</span></span><br><span class="line">    <span class="keyword">if</span>((x&lt;&lt;<span class="number">1</span> | <span class="number">1</span>)&gt;sz )</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(a[x&lt;&lt;<span class="number">1</span>]&gt;a[x])</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">swap</span>(a[x],a[x&lt;&lt;<span class="number">1</span>]);</span><br><span class="line">            <span class="built_in">pushdown</span>(x&lt;&lt;<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//左右子节点都有</span></span><br><span class="line">        <span class="keyword">if</span>(a[x] == <span class="built_in">max</span>(&#123;a[x],a[x&lt;&lt;<span class="number">1</span>],a[x&lt;&lt;<span class="number">1</span>|<span class="number">1</span>]&#125;))</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">if</span>(a[x&lt;&lt;<span class="number">1</span>]&gt;a[x&lt;&lt;<span class="number">1</span>|<span class="number">1</span>])</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">swap</span>(a[x],a[x&lt;&lt;<span class="number">1</span>]);</span><br><span class="line">            <span class="built_in">pushdown</span>(x&lt;&lt;<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">swap</span>(a[x],a[x&lt;&lt;<span class="number">1</span>|<span class="number">1</span>]);</span><br><span class="line">            <span class="built_in">pushdown</span>(x&lt;&lt;<span class="number">1</span>|<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//push函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">push</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    a[++sz] = x;</span><br><span class="line">    <span class="built_in">pushup</span>(sz);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//pop函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">pop</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    a[<span class="number">1</span>] = a[sz--];</span><br><span class="line">    <span class="built_in">pushdown</span>(<span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_21">点击此处</a></p><h4 id="链表、栈、队列">链表、栈、队列</h4><blockquote><p>用数组的方式实现</p></blockquote><p>【概念】：这一部分很多都是数据结构上讲到的东西，读者完全可以翻书查看，这里就不讲解其概念了(<strong>其实用C语言实现更加底层，更能理解其数据结构</strong>)，读者完全可以只看数据结构中是如何实现的，这里主要讲一些例题，并且用相对底层的方法解答。</p><ul><li><p><a href="https://www.lanqiao.cn/problems/3255/learning/?page=1&amp;first_category_id=1&amp;problem_id=3255">1.重新排队 - 蓝桥云课</a></p></li><li><p><a href="https://www.lanqiao.cn/problems/2490/learning/?page=1&amp;first_category_id=1&amp;problem_id=2490">1.小蓝的括号串1 - 蓝桥云课</a></p></li><li><p><a href="https://www.lanqiao.cn/problems/511/learning/?page=1&amp;first_category_id=1&amp;problem_id=511">1.机器翻译 - 蓝桥云课</a></p></li></ul><hr><p><strong>单调栈与单调队列</strong></p><p>【概念】：单调栈是一个时刻保证内部元素具有单调性质的栈，是一种线性结构。其单调特性使得处理一些问题变得高效，例如求某个点左侧或右侧第一个比它大的点的位置。单调栈的核心思想是：在<strong>入栈时逐个删除所有“更差的点”</strong>，保持单调性。单调栈一般可分为单调递减栈、单调递增栈、单调不减栈、单调不增栈，需要根据题意来确定。同时，<strong>用数组实现的单调栈会比用STL实现的更灵活</strong>，可以在里面进行二分，LIS的O(logn)算法就需要用到单调栈+二分。</p><p>【概念】：单调队列和单调栈思想类似，是一种基于“双端队列”的数据结构。单调队列内元素具有单调性质，<strong>但是大多时候我们会将“下标”作为队列中的元素，而不是“元素值”</strong>。一般来说，单调队列的队头是“最优的元素”，后面的是候选元素，每次入队时会将“没有价值的元素”直接删除。</p><p>【例题】</p><ul><li><p><a href="https://www.lanqiao.cn/problems/1142/learning/?page=1&amp;first_category_id=1&amp;problem_id=1142">1.百亿富翁 - 蓝桥云课</a></p></li><li><p><a href="https://www.lanqiao.cn/problems/3707/learning/?page=1&amp;first_category_id=1&amp;problem_id=3707">1.买蛋糕 - 蓝桥云课</a></p></li></ul><p>用单调队列分别处理出固定长度区间的最大值和最小值，然后用遍历区间[k,n],计算有多少个区间的最值之差&lt;=x,总区间个数为n-k+1,再结合逆元计算即可。</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_21">点击此处</a></p><hr><h2 id="树">树</h2><blockquote><p>同前面的部分，不对数据结构中已经详细介绍的重复介绍，而主要讲解在解题上的应用。</p></blockquote><h3 id="DFS序">DFS序</h3><p>【概念】：DFS序是指对一棵树进行DFS时，每个节点被访问到的顺序。DFS序分成两部分：进入该节点的顺序和退出该节点的顺序。</p><p>【实现】：</p><p>对于DFS中当前节点</p><ol><li>计数+</li><li>进入当前节点的顺序等于当前计数</li><li>向所有子节点继续搜索</li><li>推出当前节点的顺序等于当前计数</li></ol><p>示例代码实现如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> f)</span><span class="comment">//t表示当前节点编号，f表示父节点编号</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    in[t] = ++cnt;<span class="comment">//in数组存放的是进入改节点的顺序，cnt用来计时</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = head[t];i;i = edge[i].next)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(edge[i].n!=f)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">dfs</span>(edge[i].n,t);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    out[t] = cnt;<span class="comment">//out表示退出该节点的顺序，也就是dfs递归完回退部分</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>相关重要性质</strong></p><ul><li>某些连续的入序对应树中的节点是一条链；</li><li>某节点入序和出序之间对应的节点一定在其子树中。</li></ul><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3549/learning/?page=1&amp;first_category_id=1&amp;problem_id=3549">1.异或和 - 蓝桥云课</a></li></ul><p>基本上是在原有dfs的基础上加上dfs序的模板就可以解决</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_22">点击此处</a></p><h3 id="LCA">LCA</h3><p>【概念】：LCA(Least Common Ancestors),即最近公共祖先，是指在有根树中，找出某两个结点x和y最近的公共祖先。</p><p>【实现】：一种朴素的球阀就是枚举，不断向上找父亲直到两者的父亲相同，但是时间复杂度较高，而我们这里实现的方法是<strong>倍增法</strong>，</p><p>倍增法求LCA本质上是一个dp,类似于之前讲过的ST表。<code>fa[i][j]</code>表示i号节点，往上走2 ^ j所到的结点，当dep[i]-2^j&gt;=1时<code>fa[i][j]</code>有效（假设根节点深度为1)这个fa数组同样用dfs可以求出来，示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//当前节点为x,父亲为p</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> p)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    dep[x] = dep[p]<span class="number">+1</span>;<span class="comment">//更新dep</span></span><br><span class="line">    fa[x][<span class="number">0</span>] = p;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=<span class="number">20</span>;i++)<span class="comment">//循环更新fa</span></span><br><span class="line">    &#123;</span><br><span class="line">        fa[x][i] = fa[fa[x][i<span class="number">-1</span>]][i<span class="number">-1</span>];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//向下搜索</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;y:g[x])</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//如果y是父亲就跳过</span></span><br><span class="line">        <span class="keyword">if</span>(y == p)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">dfs</span>(y,x);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>倍增LCA中还用到了贪心的思想，在具体进行查询LCA(x,y)时，同样是假设x深度更深，然后从大到小枚举j,当<code>fa[x][j]</code>的深度不超过y的深度时，x才能往上跳。也就是说要让<strong>x往上跳，但是不能超过y,又要尽可能接近y</strong>.跳完之后必然有dep[x]=dep[y],此时如果x=y直接返回，否则再按照同样的方法<strong>同时往上跳，保持x!=y,最后一定会停留在LCA(x,y)的下方</strong>，返回<code>fa[x][0]</code>即可。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">lca</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//如果x深度比y小，就交换x,y，使得x深度更深</span></span><br><span class="line">    <span class="keyword">if</span>(dep[x]&lt;dep[y])</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">swap</span>(x,y);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//贪心的思想，i从大到小</span></span><br><span class="line">    <span class="comment">//x向上跳的过程中,保持dep[x]&gt;=dep[y]，深度不能超过y</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">20</span>;i&gt;=<span class="number">0</span>;i--)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(dep[fa[x][i]]&gt;=dep[y])</span><br><span class="line">        &#123;</span><br><span class="line">            x = fa[x][i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(y == x)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> x;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//跳跃过程中，保持x!=y</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">20</span>;i&gt;=<span class="number">0</span>;i--)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(fa[x][i]!=fa[y][i])</span><br><span class="line">        &#123;</span><br><span class="line">            x = fa[x][i];</span><br><span class="line">            y = fa[y][i];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> fa[x][<span class="number">0</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/4385/learning/?page=1&amp;first_category_id=1&amp;problem_id=4385">1.最近公共祖先LCA查询 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_22">点击此处</a></p><h3 id="树的直径与重心">树的直径与重心</h3><p>【概念】：<strong>树的直径是树上最长的一条链</strong>，当然这条链<strong>不唯一</strong>，所以一棵树可能有多条直径。直径由两个顶点u,V决定，若有一条直径u,v,则满足以下性质：1. u,v的度数均为1   2. 在以任意一个点为根的树上，<strong>u,v中必然存在一个点作为最深的叶子结点。深度就是点距离根节点的距离</strong></p><p>【实现】</p><p>树的直径有两种求法，第一种方法是“跑两遍fs”，第二种方法是树形dp。我们先讲解第一种方法“跑两遍dfs”。<br>由于直径端点u,v必然存在一个是深度最深的点，那么我们可以在<strong>以任意节点为根的树上跑一次dfs求所有点的深度，选取深度最大的点</strong>（可能有多个，任取一个）作为u,然后以u为根再跑一次dfs,此时深度最大的点(可能有多个，任取一个)就是v.于是就可以得到两个端点u,v,从而确定树的直径，<strong>其长度就是路径上点的个数</strong>，也就等于以u为根的树中的dep[v]。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3029/learning/?page=1&amp;first_category_id=1&amp;problem_id=3029">1.卖树 - 蓝桥云课</a></li></ul><p>首先，如果k&lt;=C,那么肯定不能进行移动，因为每移动一次，都会付出C的代价，但是最多使得最深的点深度+1，换来k的收益，这是不划算的。当k&gt;C时，随意画一棵树，可以将树划分为三部分。我们认为根的深度为0.换句话说，最优的位置一定是不经过直径的最深的叶子(图中的8或15)，或者v.他们两个的盈利分别是：dep[u]* k+maxdep * (k-c); dpeU[v] * k-dep[v] * c，其中dep[x]表示的是以1为根的树中x的深度，depU[x]表示的以U为根的数中x的深度。</p><p><strong>树的重心</strong></p><p>【概念】：树的重心是指对于某个点，<strong>将其删除后，可以使得剩余联通块的大小的点</strong>。也就<strong>等价于以某个点为根的树，将根删除后，剩余</strong><br><strong>的若干棵子树的大小最小</strong>。我们先学习重心的若干性质，然后学习其求法（很简单）我们用mss[x]表示x点的所有子树大小的最大值。注意，此时我们认为除去x及其子树剩余的部分也是x的子树。</p><p>相关性质</p><ul><li>性质一：<strong>重心的若干棵子树的大小一定&lt;=n</strong>(n为总节点个数),除了重心以外的所有其他点，都必然存在一棵节点个数&gt;n的子树。</li><li>性质二：一棵树至多两个重心，如果存在两个重心，则必然相邻，将连接两个重心的边删除后，一定划分为两棵大小相等的树。</li><li>性质三：树中所有点到某个点的距离和中，到重心的距离和是最小的；如果有两个重心，那么到它们的距离和一样。反过来，距离和最小的点一定是重心。</li><li>性质四：把两棵树通过一条边相连得到一棵新的树，则新的重心在较大的一棵树一侧的连接点与原重心之间的简单路径上。如果两棵树大小一样，则重心就是两个连接点。</li></ul><p>【实现】：非常简单，跑一遍dfs，如果mss[x]&lt;=n/2,则x是重心，反之不是</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> fa)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    sz[x] = <span class="number">1</span>,mss[x] = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;y:g[x])</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(y == fa)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">dfs</span>(y,x);</span><br><span class="line">        sz[x]+=sz[y];</span><br><span class="line">        mss[x] = <span class="built_in">max</span>(mss[x],sz[y]);</span><br><span class="line">    &#125;</span><br><span class="line">    mss[x] = <span class="built_in">max</span>(mss[x],n-sz[x]);</span><br><span class="line">    <span class="keyword">if</span>(mss[x]&lt;=n/<span class="number">2</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        v.<span class="built_in">push_back</span>(x);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_22">点击此处</a></p><h3 id="树链剖分">树链剖分</h3><p>【概念】：树链剖分（树剖）用于将树分割成若干条链的形式，以维护树上路径的信息。</p><p><strong>重链剖分</strong>：重链剖分优先使用重儿子延续当前链，轻儿子则另开新链。重儿子指某节点的所有儿子中，<strong>子树大小最大的儿子</strong>，其他儿子均为轻儿子。</p><p>示例的数据结构如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> ord;<span class="comment">//DFS序计数</span></span><br><span class="line"><span class="type">int</span> rnk[MAXN];<span class="comment">//rnk[i]代表入序为i的节点编号</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">NODE</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> fa;<span class="comment">//当前节点的父节点</span></span><br><span class="line">    <span class="type">int</span> in;<span class="comment">//当前节点的DFS入序</span></span><br><span class="line">    <span class="type">int</span> out;<span class="comment">//当前节点的DFS出序</span></span><br><span class="line">    <span class="type">int</span> son;<span class="comment">//当前节点的重儿子编号</span></span><br><span class="line">    <span class="type">int</span> top;<span class="comment">//当前节点所需链的首节点编号</span></span><br><span class="line">    <span class="type">int</span> deep;<span class="comment">//当前节点在树中的深度</span></span><br><span class="line">    <span class="type">int</span> size;<span class="comment">//当前节点的子树大小</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>【实现】：一般是通过两次dfs实现的，第一次预处理出每个节点的基本信息：深度、子树大小、父节点、重儿子,第二次利用前边预处理出的信息对树进行剖分。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第一次的dfs</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs1</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> fa)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">node[t].size = <span class="number">1</span>;</span><br><span class="line">node[t].fa = fa;</span><br><span class="line">node[t].deep = node[fa].deep<span class="number">+1</span>;</span><br><span class="line"><span class="keyword">for</span>(itn i = head[t];i;i = edge[i].next) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(edge[i].n!=fa)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">dfs1</span>(edge[i].n,t);</span><br><span class="line">node[t].<span class="built_in">size</span>() += node[edge[i].n].<span class="built_in">size</span>();</span><br><span class="line"><span class="keyword">if</span>(node[edge[i].n].size&gt; node[node[t].son].size)</span><br><span class="line">&#123;</span><br><span class="line">node[t].son = edge[i].n;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第二次dfs</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs2</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> fa,<span class="type">int</span> top)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    node[t].top = top;</span><br><span class="line">    node[t].in = ++ord;</span><br><span class="line">    rnk[ord] = t;</span><br><span class="line">    <span class="keyword">if</span>(node[t].son)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">dfs2</span>(node[t].son,t,top);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = head[t];i;i = edge[i].next)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(edge[i].n != fa &amp;&amp; edge[i].n != node[t].son)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">dfs2</span>(edge[i].n,t,edge[i].n);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    node[t].out = ord;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>相关的性质</strong>:每一条链子的dfs序都是连续的</p><p>相关的操作</p><p>查询两节点的最近公共祖先</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">lca</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(node[x].top!=node[y].top)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(node[node[x].top].deep&lt;node[node[y].top].deep)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">swap</span>(x,y);</span><br><span class="line">        &#125;</span><br><span class="line">        x = node[node[x].top].fa;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> node[x].deep&gt;node[y].deep?y:x;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>修改两个节点之间的路径信息</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y,ll k)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(node[x].top!=node[y].top)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(node[node[x].top].deep&lt;node[node[y].top].deep)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">swap</span>(x,y);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">update_v</span>(<span class="number">1</span>,<span class="number">1</span>,ord,node[node[x].top].in,node[x].in,k);</span><br><span class="line">        x = node[node[x].top].fa;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(node[x].deep&lt;node[y].deep)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">swap</span>(x,y);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">update_v</span>(<span class="number">1</span>,<span class="number">1</span>,ord,node[y].in,node[x].in,k);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="树上差分">树上差分</h3><p>【例题引入】：树上差分有什么作用？举个例子，如果题目要求对树上的一段路径进行操作，并询问某个点或某条边被经过的次数，树上差分就可以派上用场了。这就是树上差分的基本操作。树上差分，就是利用差分的性质，对路径上的重要节点进行修改而不是暴力全改），作为其差分数组的值，最后在求值时，利用dfs遍历求出差分数组的前缀和，就可以达到降低复杂度的目的。需要注意的是<strong>树上差分需要求LCA</strong>，</p><p>【例题】：</p><ul><li>现在有一棵树，给定条路径，每条路径给定两个端点，两个端点之间的路径所覆盖的点进行染色，问每一个点被染色了多少次。</li></ul><p>本问题的实现代码在文件名为<code>TreeDiff.cpp</code>文件中</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_23">点击此处</a></p><h3 id="主席树">主席树</h3><p>【概念】：主席树，全称可持久化权值线段树。所谓可持久化，就是对于每次操作，都保留其历史版本(有点像是git(❁´◡`❁))</p><p>【实现】：以下主要讲解其数据结构</p><ol><li>建树</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">NODE</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//v表示该节点的值,ls与rs表示该节点的左右子节点编号</span></span><br><span class="line">    <span class="type">int</span> v,ls,rs;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">SEGTREE</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">//cnt记录节点的数量</span></span><br><span class="line">    <span class="type">int</span> cnt = <span class="number">0</span>;</span><br><span class="line">    <span class="comment">//root[i]表示第i个版本的根节点</span></span><br><span class="line">    <span class="type">int</span> root[MAXN&lt;&lt;<span class="number">5</span>];</span><br><span class="line">    NODE node[MAXN&lt;&lt;<span class="number">5</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>更新：一、如果当前节点未创建，则创建该节点，复制原节点信息。二、如果左儿子需要更新，则将原来的右儿子作为当前节点的右儿子；如果右儿子需要更新，则将原来的左儿子作为当前节点的左儿子；三、最终进入下一层递归，未创建的儿子节点将在下一层创建</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//_t表示原节点编号 t表示当前新节点编号 l,r表示当前节点的区间 pos表示待更新的位置，k为更新的目标值</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">SETGTREE::update</span><span class="params">(<span class="type">int</span> <span class="type">_t</span>,<span class="type">int</span> &amp;t,<span class="type">int</span> l.<span class="type">int</span> r.<span class="type">int</span> pos,<span class="type">int</span> k)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!t)</span><br><span class="line">    &#123;</span><br><span class="line">        t = cnt++;</span><br><span class="line">        node[t].v = node[<span class="type">_t</span>].v;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(l == r)</span><br><span class="line">    &#123;</span><br><span class="line">        node[t].v+=k;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l+r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span>(pos&lt;=mid)</span><br><span class="line">    &#123;</span><br><span class="line">        node[t].rs = node[<span class="type">_t</span>].rs;</span><br><span class="line">        <span class="built_in">update</span>(node[<span class="type">_t</span>].ls,node[t].ls,l,mid,pos,k);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        node[t].ls = node[<span class="type">_t</span>].ls;</span><br><span class="line">        <span class="built_in">update</span>(node[<span class="type">_t</span>].rs,node[t].rs,mid<span class="number">+1</span>,r,pos,k);</span><br><span class="line">    &#125;</span><br><span class="line">    node[t].v = node[node[t].ls].v+node[node[t].rs].v;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li>查询：如果当前节点未创建，则返回0；如果已经找到目标区间，返回该区间的值；如果未找到目标区间，则进入下一层递归。</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//t为当前节点的编号,_l,_r表示当前节点的区间,l,r表示待查询的区间。</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">SEGTREE::getV</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> _l,<span class="type">int</span> _r,<span class="type">int</span> l,<span class="type">int</span> r)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!t)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(l == _l &amp;&amp; r == _r)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> node[t].v;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (_l+_r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span>(r&lt;=mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getV</span>(node[t].ls,_l,mid,l,r);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(l&gt;mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getV</span>(node[t].rs,mid<span class="number">+1</span>,_r,l,r);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getV</span>(node[t].ls,_l,mid,l,mid)+<span class="built_in">getV</span>(node[t].rs,mid<span class="number">+1</span>,_r,mid<span class="number">+1</span>,r);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1132/learning/?page=1&amp;first_category_id=1&amp;name=%E5%8C%BA%E9%97%B4%E7%AC%ACk%E5%B0%8F">1.区间第k小 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_23">点击此处</a></p><h3 id="伸展树">伸展树</h3><blockquote><p>考的比较少，后续补上，就是平衡二叉查找树的pro max版本，相关操作也基本上是平衡二叉树的。</p></blockquote><h3 id="树状数组">树状数组</h3><p>【概念】：树状数组是一种可以 “<strong>动态求区间和</strong>”的树形数据结构，但并没有真正地构造出边来，所以是“树状”的。基础的树状数组可以实现对区间和的<strong>单点修改和区间查询</strong></p><p>在学习树状数组之前，我们需要了解lowbit操作，这是一种位运算操作，用于计算出数字的二进制表达史的最低位的1以及后面所有的0。</p><p>其实现方法如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">lowbit</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x &amp; -x;<span class="comment">//利用计算机存储整数的特性，因为在计算机中整数都是使用补码存储，原理不需要掌握，只需要会用就行。</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>接下来讲解树状数组的数据结构。其中t[i]存储a数组中一段区间的和，我们定义是让t[i]存储以i结尾，且区间大小为lowbit(i)的区间的和</p><p>其公式为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>t</mi><mi>i</mi></msub><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mi>i</mi><mo>−</mo><mi>l</mi><mi>o</mi><mi>w</mi><mi>b</mi><mi>i</mi><mi>t</mi><mo stretchy="false">(</mo><mi>i</mi><mo stretchy="false">)</mo><mo>+</mo><mn>1</mn></mrow><mi>i</mi></msubsup><msub><mi>a</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">t_i = \sum_{j=i-lowbit(i)+1}^{i}a_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7651em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4393em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9646em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">t</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">)</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 习惯上叫[i-lowbit(i)+1,i]为i的管辖区间。</p><p>怎么进行单点修改？举个例子，假如我要修改a[3]，让他加上x，应该修改t[3],t[4]和t[8]共3个节点，因为这三个节点的管辖区间内都包含3这个节点。但是我们如何从3开始，去找到3,4,8呢？只需要进行+lowbit操作即可（二进制性质）。3 + lowbit(3) = 4</p><p>怎么进行区间查询？第一步我们将其拆为两个区间的差，举个例子我们要查询区间[3,7]的和，就要拆分为sum[1,7]-sum[1,2](前缀和的写法) 现在问题变为如何查询[1,k]的和？假如我们要求sum[1,7]，可以知道结果为t[7]+t[6]+t[4]，这是怎么得到的呢？通过-lowbit即可：7 - lowbit(7) = 6,6-lowbit(6) = 4;</p><p>【实现】根据以上的分析可以写出以下的代码</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//给a[k]增加x</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> k,<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = k;i&lt;=n;i+=<span class="built_in">lowbit</span>(i))</span><br><span class="line">    &#123;</span><br><span class="line">        t[i]+=x;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回区间[1,k]的和</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">getprefix</span><span class="params">(<span class="type">int</span> k)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = k;i&gt;<span class="number">0</span>;i-=<span class="built_in">lowbit</span>(i))</span><br><span class="line">    &#123;</span><br><span class="line">        res+=t[i];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/3620/learning/?page=1&amp;first_category_id=1&amp;problem_id=3620">1.殷老师排队 - 蓝桥云课</a></li></ul><p>这一题就是要用树状数组实现</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_24">点击此处</a></p><p><strong>树状数组的二分</strong></p><p>【例题引入】：给出三种操作，分别是：在容器中插入一个数；在容器中删除一个数；求出容器中大于a的第k大元素。</p><p>树状数组的特点就是<strong>对点更新，成段求和</strong>，而且常数非常小。原始的树状数组只有两种操作，在某点插入一个数和求1到i的所有数的和。这道题目一共有三种操作，但是实质上其实只有两种：插入和询问。插入操作和删除操作可以视为一种，只不过一个是将标记+1，另一个是-1,而插入的数对应于树状数组的下标，这样就可以在log(n)的时间内完成插入和删除。求大于a的k大元素，可以通过二分枚举答案来完成，枚举的是当前答案在树状数组中的位置，设为m，然后对v[a+1]  v[m]求和就是小于等于m的数的个数，这一步可以用树状数组的求和操作来完成，然后根据和k的比较来调整m的位置</p><p>实现的代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">110000</span>;</span><br><span class="line"><span class="type">int</span> tree[MAXN];</span><br><span class="line"><span class="type">int</span> q;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">lowbit</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> x &amp; -x;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> pos,<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(pos&lt;MAXN)</span><br><span class="line">    &#123;</span><br><span class="line">        tree[pos]+=x;</span><br><span class="line">        pos+=<span class="built_in">lowbit</span>(pos);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">query</span><span class="params">(<span class="type">int</span> pos)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(pos)</span><br><span class="line">    &#123;</span><br><span class="line">        ans+=tree[pos];</span><br><span class="line">        pos-=<span class="built_in">lowbit</span>(pos);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ans;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">find</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> k)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> l = a<span class="number">+1</span>,r = MAXN<span class="number">-1</span>;</span><br><span class="line">    <span class="type">int</span> ans = <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">while</span>(l&lt;=r)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> mid = (l+r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">        <span class="keyword">if</span>(<span class="built_in">query</span>(mid)-<span class="built_in">query</span>(a) == k)</span><br><span class="line">        &#123;</span><br><span class="line">            ans = mid;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span>(<span class="built_in">query</span>(mid)-<span class="built_in">query</span>(a)&gt;=k)</span><br><span class="line">        &#123;</span><br><span class="line">            r = mid<span class="number">-1</span>;</span><br><span class="line">        &#125; </span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">        &#123;</span><br><span class="line">            l = mid<span class="number">+1</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> ans;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>,&amp;q);</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=q;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> x,y,z;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>,&amp;x);</span><br><span class="line">        <span class="keyword">if</span>(x == <span class="number">0</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>,&amp;y);</span><br><span class="line">            <span class="built_in">add</span>(y,<span class="number">1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(x == <span class="number">1</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>,&amp;y);</span><br><span class="line">            <span class="keyword">if</span>(<span class="built_in">query</span>(y)-<span class="built_in">query</span>(y<span class="number">-1</span>) == <span class="number">0</span>)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="built_in">add</span>(y,<span class="number">-1</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>,&amp;y,&amp;z);</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>,<span class="built_in">find</span>(y,z)) ;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="线段树">线段树</h3><p>【概念】：相关的概念介绍和图形示例可以看这篇博客<a href="https://blog.csdn.net/weixin_45697774/article/details/104274713">线段树 从入门到进阶（超清晰，简单易懂）_进阶线段树-CSDN博客</a> 简单来说线段树是一种方便进行区间查询和单点修改的树，前面讲过的树状数组也是类似的实现。</p><h4 id="标记永久化">标记永久化</h4><p>在线段树的区间修改中，一般的处理方法是在待修改区间上使用懒惰标记(LazyFlag)，当访问到该节点时，再将懒惰标记下传。标记永久化是将懒惰标记永远标记在对应区间，在访问到该节点时，不下传标记，而是直接将标记累加，最终计算出该标记对结果的影响。</p><p>【实现】</p><ol><li>建树：和前面主席树基本一样,一般的线段树也是这样建立的</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">build</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> l,<span class="type">int</span> r,<span class="type">int</span> *v)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    _l[t] = l;</span><br><span class="line">    -r[t] = r;</span><br><span class="line">    <span class="keyword">if</span>(l == r)</span><br><span class="line">    &#123;</span><br><span class="line">        _v[t] = v[l];</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l+r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="built_in">build</span>(t&lt;&lt;<span class="number">1</span>,l,mid,v);</span><br><span class="line">    <span class="built_in">build</span>(t&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,mid<span class="number">+1</span>,r,v);</span><br><span class="line">    _v[t] = _v[t&lt;&lt;<span class="number">1</span>]+_v[t&lt;&lt;<span class="number">1</span>|<span class="number">1</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>在更新时，对上层区间进行修改，在待修改区间更新标记</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> l,<span class="type">int</span> r,<span class="type">int</span> k)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    _v[t]+=k*(r-l<span class="number">+1</span>);</span><br><span class="line">    <span class="keyword">if</span>(_l[t] == l &amp;&amp; _r[t] == r)</span><br><span class="line">    &#123;</span><br><span class="line">        _laz[t]+=k;</span><br><span class="line">        <span class="keyword">return</span> ;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (_l[t]+_r[t])&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span>(r&lt;=mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">update</span>(t&lt;&lt;<span class="number">1</span>,l,r,k);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(l&gt;mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">update</span>(t&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,l,r,k);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">update</span>(t&lt;&lt;<span class="number">1</span>,l,mid,k);</span><br><span class="line">        <span class="built_in">update</span>(t&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,mid<span class="number">+1</span>,r,k)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li>区间查询:在查询时，逐层累加上层区间标记，在带查询区间计算值。</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">getv</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> l,<span class="type">int</span> r,<span class="type">int</span> sum)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(_l[t] == l&amp;&amp; _r[t] == r)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> _v[t]+sum*(_r[t]-_l[t]<span class="number">+1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (_l[t]+_r[t])&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span>(r&lt;=mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getv</span>(t&lt;&lt;<span class="number">1</span>,l,r,sum+_laz[t]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(l&gt;mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getv</span>(t&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,l,r,sum+_laz[t]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getv</span>(t&lt;&lt;<span class="number">1</span>,l,mid,sum+_laz[t])+<span class="built_in">getv</span>(t&lt;&lt;<span class="number">1</span>|<span class="number">1</span>,mid<span class="number">+1</span>,r,sum+_laz[t]);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="动态开点">动态开点</h4><p>【概念】：传统线段树中维护长度为n的区间，需要4n大小的数组。为了节省空间，我们可以不一次性建好树，而是在最初只建立一个根结点代表整个区间。当我们需要访问某个子区间时，才建立代表这个区间的子结点。这就是动态开点。也就是说，<strong>动态开点线段树的核心就是：节点只有在被需要的时候才会被创建</strong>。</p><p>【实现】</p><ol><li>建树</li></ol><p>动态开点不需要像普通线段树一样建树，只需要初始化根节点。并且由于动态开点，节点的子节点再是2p和2p+1，而是使用变量ls,rs存储子节点编号。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//l,r为该节点维护的区间 ls,rs表示该节点的左右子节点编号 n表示该节点的值</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Tree</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> l,r,n,ls,rs;<span class="comment">//</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>修改节点</li></ol><p>在更新时，判断当前节点是否存在，如果不存在则开点。以单点修改为例。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//其中t为当前节点编号 l,r为当前区间，pos为要修改的位置,n为目标值</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> &amp;t,<span class="type">int</span> l,<span class="type">int</span> r,<span class="type">int</span> pos,<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!t)</span><br><span class="line">    &#123;</span><br><span class="line">        t == ++cnt;</span><br><span class="line">        tree[t].l = l;</span><br><span class="line">        tree[t].r = r;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(l == r)</span><br><span class="line">    &#123;</span><br><span class="line">        tree[t].n = n;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l+r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span>(pos&lt;=mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">update</span>(tree[t].ls,l,mid,pos,n);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">update</span>(tree[t].rs,mid<span class="number">+1</span>,r,pos,n);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li>查询</li></ol><p>在查询时，判断当前节点是否存在，如果不存在则返回0。以区间查询为例。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//其中t为当前节点编号,l,r为当前区间</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">getnum</span><span class="params">(<span class="type">int</span> t,<span class="type">int</span> l,<span class="type">int</span> r)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(!t)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(tree[t].l == l &amp;&amp; tree[t].r == r)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> tree[t].n;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (tree[t].l+tree[t].r)&gt;&gt;<span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span>(r&lt;=mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getnum</span>(tree[t].ls,l,r);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span> <span class="keyword">if</span>(l &gt; mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getnum</span>(tree[t].rs,l,r);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">getnum</span>(tree[t].ls,l,mid)+<span class="built_in">getnum</span>(tree[t],mid<span class="number">+1</span>,r);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li>给定一个长度为N的非负整数序列A，对于前奇数项求中位数 其中输入格式为第一行一个正整数N.第二行N个正整数A1…N。请输出[(N+1)/2]行，第i行为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mn>1</mn></msub><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><msub><mi>A</mi><mrow><mn>2</mn><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">A_1...A_{2i-1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">...</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span>的中位数</li></ul><p>代码示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">1e5</span><span class="number">+7</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> INF = <span class="number">1e9</span><span class="number">+7</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Tree</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> l, r, v, num, ls, rs; </span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> root, cnt;</span><br><span class="line">Tree tre[MAXN &lt;&lt; <span class="number">4</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">update</span><span class="params">(<span class="type">int</span> &amp;t, <span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> k)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!t)</span><br><span class="line">    &#123;</span><br><span class="line">        t = ++cnt;</span><br><span class="line">        tre[t].l = l;</span><br><span class="line">        tre[t].r = r;</span><br><span class="line">        tre[t].num = <span class="number">0</span>; <span class="comment">// 初始化 num</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (l == r)</span><br><span class="line">    &#123;</span><br><span class="line">        tre[t].v = k;</span><br><span class="line">        tre[t].num++;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l + r) &gt;&gt; <span class="number">1</span>;</span><br><span class="line">    <span class="keyword">if</span> (k &lt;= mid)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (!tre[t].ls) tre[t].ls = ++cnt;</span><br><span class="line">        <span class="built_in">update</span>(tre[t].ls, l, mid, k);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (!tre[t].rs) tre[t].rs = ++cnt;</span><br><span class="line">        <span class="built_in">update</span>(tre[t].rs, mid + <span class="number">1</span>, r, k);</span><br><span class="line">    &#125;</span><br><span class="line">    tre[t].num = (tre[t].ls ? tre[tre[t].ls].num : <span class="number">0</span>) + (tre[t].rs ? tre[tre[t].rs].num : <span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 找中位数函数 </span></span><br><span class="line"><span class="comment">// t表示当前节点 k剩余排名 </span></span><br><span class="line"><span class="type">int</span> _rank(<span class="type">int</span> t, <span class="type">int</span> k)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (tre[t].l == tre[t].r)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> tre[t].v;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (tre[tre[t].ls].num &gt;= k)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> _rank(tre[t].ls, k);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> _rank(tre[t].rs, k - tre[tre[t].ls].num);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">// 初始化</span></span><br><span class="line">    <span class="type">int</span> x, y;</span><br><span class="line">    cin &gt;&gt; n &gt;&gt; x;</span><br><span class="line">    <span class="built_in">update</span>(root, <span class="number">0</span>, INF, x);</span><br><span class="line">    cout &lt;&lt; x &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">3</span>; i &lt;= n; i += <span class="number">2</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        cin &gt;&gt; x &gt;&gt; y;</span><br><span class="line">        <span class="built_in">update</span>(root, <span class="number">0</span>, INF, x);</span><br><span class="line">        <span class="built_in">update</span>(root, <span class="number">0</span>, INF, y);</span><br><span class="line">        cout &lt;&lt; _rank(root, i / <span class="number">2</span> + <span class="number">1</span>) &lt;&lt; endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_24">点击此处</a></p><h4 id="线段树维护哈希">线段树维护哈希</h4><p>【例题引入】：给定长度为从的仅由小写英文字母构成的字符串 S= S1,S2,…，Sn，定义它的子串 S[l, r] = Sl, Sl+1, . …, Sr.<br>有以下两种操作：</p><ol><li><p>ad ch：将字符串中第ad个元素sad赋值为字符ch，给定的ch仅可能是小写英文字母。</p></li><li><p>l1 r1 12 r2:请你判断字符串 S[l1,r1] 是否等于 S[l2,r2]。</p></li></ol><p>共进行q次操作，对于第二种操作，若两个子串相等则输出YES，否则输出 NO。</p><p>如果想要快速匹配对应的字符串是否想等，应该考虑的是用<strong>哈希值</strong>而不是kmp算法，而要维护区间信息的话最好使用<strong>线段树</strong></p><p>但是怎么合并两个相邻区间的哈希值呢？比如对于哈希值来说 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>h</mi><mi>A</mi></msub><mo>=</mo><msub><mi>h</mi><mi>B</mi></msub><mo>×</mo><mi>b</mi><mi>a</mi><mi>s</mi><msup><mi>e</mi><mrow><mi>l</mi><mi>e</mi><msub><mi>n</mi><mi>C</mi></msub></mrow></msup><mo>+</mo><msub><mi>h</mi><mi>C</mi></msub></mrow><annotation encoding="application/x-tex">h_A = h_B \times base^{len_{C}}+h_C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9324em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">ba</span><span class="mord mathnormal">s</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">e</span><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1433em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>  长度 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi><mi>e</mi><msub><mi>n</mi><mi>A</mi></msub><mo>=</mo><mi>l</mi><mi>e</mi><msub><mi>n</mi><mi>B</mi></msub><mo>+</mo><mi>l</mi><mi>e</mi><msub><mi>n</mi><mi>C</mi></msub></mrow><annotation encoding="application/x-tex">len_A = len_B+len_C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>可以总结成<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>h</mi><mi>A</mi></msub><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>l</mi><mi>e</mi><msub><mi>n</mi><mi>A</mi></msub></mrow></msubsup><msub><mi>S</mi><mrow><mi>b</mi><mi>g</mi><mo>+</mo><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>×</mo><mi>b</mi><mi>a</mi><mi>s</mi><msup><mi>e</mi><mrow><mi>l</mi><mi>e</mi><msub><mi>n</mi><mrow><mi>A</mi><mo>−</mo><mi>i</mi></mrow></msub></mrow></msup><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>M</mi><mo stretchy="false">)</mo></mspace></mspace></mrow><annotation encoding="application/x-tex">h_A = \sum_{i=1}^{len_{A}}S_{bg+i-1}\times base^{len_{A-i}} \pmod M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2887em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.989em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">e</span><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1433em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mbin mtight">+</span><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord mathnormal">ba</span><span class="mord mathnormal">s</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">e</span><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2028em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mclose">)</span></span></span></span></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> ll base = <span class="number">233</span>, mod = <span class="number">998244353</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">2000005</span>;</span><br><span class="line">ll bs[MAXN] = &#123;<span class="number">1</span>&#125;;</span><br><span class="line">string a;</span><br><span class="line"><span class="type">int</span> n, q;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">asdf</span> &#123;</span><br><span class="line">    <span class="type">int</span> len;</span><br><span class="line">    ll h;</span><br><span class="line">    asdf <span class="keyword">operator</span> + (<span class="type">const</span> asdf &amp;c) <span class="type">const</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> &#123;len + c.len, (h * bs[c.len] + c.h) % mod&#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">bool</span> <span class="keyword">operator</span> == (<span class="type">const</span> asdf &amp;c) <span class="type">const</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> len == c.len &amp;&amp; h == c.h;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">asdf s[MAXN * <span class="number">4</span>];</span><br><span class="line"></span><br><span class="line"><span class="function">asdf <span class="title">build</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> rt)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (l == r) &#123;</span><br><span class="line">        <span class="keyword">return</span> s[rt] = &#123;<span class="number">1</span>, a[l] - <span class="string">&#x27;a&#x27;</span>&#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l + r) / <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">return</span> s[rt] = <span class="built_in">build</span>(l, mid, rt * <span class="number">2</span>) + <span class="built_in">build</span>(mid + <span class="number">1</span>, r, rt * <span class="number">2</span> + <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">asdf <span class="title">modify</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> rt, <span class="type">int</span> ad, <span class="type">char</span> ch)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (l == r) &#123;</span><br><span class="line">        <span class="keyword">return</span> s[rt] = &#123;<span class="number">1</span>, ch - <span class="string">&#x27;a&#x27;</span>&#125;;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l + r) / <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">if</span> (ad &lt;= mid) &#123;</span><br><span class="line">        <span class="keyword">return</span> s[rt] = <span class="built_in">modify</span>(l, mid, rt * <span class="number">2</span>, ad, ch) + s[rt * <span class="number">2</span> + <span class="number">1</span>];</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> s[rt] = s[rt * <span class="number">2</span>] + <span class="built_in">modify</span>(mid + <span class="number">1</span>, r, rt * <span class="number">2</span> + <span class="number">1</span>, ad, ch);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">asdf <span class="title">query</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> rt, <span class="type">int</span> x, <span class="type">int</span> y)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (x &lt;= l &amp;&amp; r &lt;= y) &#123;</span><br><span class="line">        <span class="keyword">return</span> s[rt];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> mid = (l + r) / <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">if</span> (y &lt;= mid) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">query</span>(l, mid, rt * <span class="number">2</span>, x, y);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (x &gt; mid) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">query</span>(mid + <span class="number">1</span>, r, rt * <span class="number">2</span> + <span class="number">1</span>, x, y);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">query</span>(l, mid, rt * <span class="number">2</span>, x, y) + <span class="built_in">query</span>(mid + <span class="number">1</span>, r, rt * <span class="number">2</span> + <span class="number">1</span>, x, y);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    cin &gt;&gt; n &gt;&gt; a;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        bs[i] = bs[i - <span class="number">1</span>] * base % mod;</span><br><span class="line">    &#125;</span><br><span class="line">    a = <span class="string">&quot;!&quot;</span> + a;</span><br><span class="line">    <span class="built_in">build</span>(<span class="number">1</span>, n, <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">for</span> (cin &gt;&gt; q; q--;) &#123;</span><br><span class="line">        <span class="type">int</span> opt;</span><br><span class="line">        cin &gt;&gt; opt;</span><br><span class="line">        <span class="keyword">if</span> (opt == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="type">int</span> ad;</span><br><span class="line">            <span class="type">char</span> ch;</span><br><span class="line">            cin &gt;&gt; ad &gt;&gt; ch;</span><br><span class="line">            <span class="built_in">modify</span>(<span class="number">1</span>, n, <span class="number">1</span>, ad, ch);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="type">int</span> l1, r1, l2, r2;</span><br><span class="line">            cin &gt;&gt; l1 &gt;&gt; r1 &gt;&gt; l2 &gt;&gt; r2;</span><br><span class="line">            asdf x = <span class="built_in">query</span>(<span class="number">1</span>, n, <span class="number">1</span>, l1, r1);</span><br><span class="line">            asdf y = <span class="built_in">query</span>(<span class="number">1</span>, n, <span class="number">1</span>, l2, r2);</span><br><span class="line">            <span class="keyword">if</span> (x == y) &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;YES\n&quot;</span>;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                cout &lt;&lt; <span class="string">&quot;NO\n&quot;</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="分块">分块</h2><p>【概念】：分块是一种思想，把一个整体划分为若干个小块，对整块整体处理，零散块单独处理。块状数组把一个长度为n的数组划分为a块，每块长度为n/a,对于一次区间操作，对区间内部的整块进行整体的操作，对区间边缘的零散块单独暴力处理，所以分块被称为“<strong>优雅的暴力</strong>”。</p><p>【例题引入】：给出一个长为n的数列，以及n个操作，操作涉及区间加法、单点查值。n&lt;=1e5</p><p>实现思路如下</p><ol><li>.将一个长度为n的序列分为T块，每一块的长度为n/T。</li><li>分情况处理操作，假设处理的区间为[l,r]<ol><li>如果[l,r]这个区间在一个整块里面，就暴力处理</li><li>如果[l,r]跨越了一个整块，那么就整体处理整块，暴力处理零散。s</li></ol></li></ol><p>示例实现代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">110000</span>;</span><br><span class="line"><span class="type">int</span> n, a[MAXN];</span><br><span class="line"><span class="type">int</span> blo, bl[MAXN], v[MAXN], add[MAXN];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add1</span><span class="params">(<span class="type">int</span> l, <span class="type">int</span> r, <span class="type">int</span> c)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = l; i &lt;= <span class="built_in">min</span>(bl[l] * blo, r); i++) &#123;</span><br><span class="line">        v[i] += c;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (bl[l] != bl[r]) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> i = bl[l] + <span class="number">1</span>; i &lt;= bl[r] - <span class="number">1</span>; i++) &#123;</span><br><span class="line">            add[i] += c;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = (bl[r] - <span class="number">1</span>) * blo + <span class="number">1</span>; i &lt;= r; i++) &#123;</span><br><span class="line">        v[i] += c;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;n);</span><br><span class="line">    blo = <span class="built_in">sqrt</span>(n); <span class="comment">// 当成块的大小</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;a[i]);</span><br><span class="line">        v[i] = a[i];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        bl[i] = (i - <span class="number">1</span>) / blo + <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        <span class="type">int</span> op;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;op);</span><br><span class="line">        <span class="keyword">if</span> (op == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="type">int</span> l, r, c;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">&quot;%d%d%d&quot;</span>, &amp;l, &amp;r, &amp;c);</span><br><span class="line">            <span class="built_in">add1</span>(l, r, c);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="type">int</span> x;</span><br><span class="line">            <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;x);</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>, v[x] + add[bl[x]]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_25">点击此处</a></p><h3 id="莫队算法">莫队算法</h3><p>【例题引入】：考虑这样一个问题，有一个含有n个元素的序列，有m次询问，每次询问给出一个区间，要求输出该区间在满足某种性质下的答案。允许离线处理。n个元素，m次询问，每次询问给定一个区间[,r]，要求你输出这个区间内出现的数的种类个数。n,m&lt;=10^5</p><p>注意：这个问题的答案满足这样一个性质，已知区间[,r]的答案，可以以0(1)的时间复杂度推出相邻区间的答案。元素个数和询问个数同阶。</p><p>莫队算法是怎么解决这类问题的呢，首先，把序列分成若干块。然后，我们注意这类问题有一个很好的性质，我们没有用到，题目注意里说明了相邻区间的答案可以O(1)互推，这启发我们可以将所有询问离线下来，通过合适的处理顺序优化复杂度，而莫队也是这么做的，具体做法是：以区间的左端点所在的块为第一关键字，右端点为第二关键字排序，考虑我们这么做可以得到什么，不难发现，我们可以将所有询问按左端点所在的块分成若干组，然后对于同一组内的，暴力转移</p><p>【实现】</p><p>示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">1100000</span>;</span><br><span class="line"><span class="type">int</span> n, m, a[MAXN], cnt[MAXN], ans[MAXN], bel[MAXN], l = <span class="number">1</span>, r;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Node</span> &#123;</span><br><span class="line">    <span class="type">int</span> l, r, id;</span><br><span class="line">&#125; q[MAXN];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(Node a, Node b)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (bel[a.l] != bel[b.l]) &#123;</span><br><span class="line">        <span class="keyword">return</span> bel[a.l] &lt; bel[b.l];</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> a.r &lt; b.r;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> res;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">add</span><span class="params">(<span class="type">int</span> x)</span> </span>&#123;</span><br><span class="line">    cnt[a[x]]++;</span><br><span class="line">    <span class="keyword">if</span> (cnt[a[x]] == <span class="number">1</span>) &#123;</span><br><span class="line">        ++res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">del</span><span class="params">(<span class="type">int</span> x)</span> </span>&#123;</span><br><span class="line">    --cnt[a[x]];</span><br><span class="line">    <span class="keyword">if</span> (cnt[a[x]] == <span class="number">0</span>) &#123;</span><br><span class="line">        --res;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;n);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++) &#123;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;a[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> blockSize = <span class="built_in">sqrt</span>(n);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= <span class="built_in">ceil</span>((<span class="type">double</span>)n / blockSize); i++) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = (i - <span class="number">1</span>) * blockSize + <span class="number">1</span>; j &lt;= <span class="built_in">min</span>(n, i * blockSize); j++) &#123;</span><br><span class="line">            bel[j] = i;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;m);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++) &#123;</span><br><span class="line">        <span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>, &amp;q[i].l, &amp;q[i].r);</span><br><span class="line">        q[i].id = i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">sort</span>(q + <span class="number">1</span>, q + m + <span class="number">1</span>, cmp);</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++) &#123;</span><br><span class="line">        <span class="keyword">while</span> (l &lt; q[i].l) &#123;</span><br><span class="line">            <span class="built_in">del</span>(l++);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (l &gt; q[i].l) &#123;</span><br><span class="line">            <span class="built_in">add</span>(--l);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (r &lt; q[i].r) &#123;</span><br><span class="line">            <span class="built_in">add</span>(++r);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">while</span> (r &gt; q[i].r) &#123;</span><br><span class="line">            <span class="built_in">del</span>(r--);</span><br><span class="line">        &#125;</span><br><span class="line">        ans[q[i].id] = res;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%d &quot;</span>, ans[i]);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;\n&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_25">点击此处</a></p><hr><h2 id="图论">图论</h2><h3 id="图的基本知识">图的基本知识</h3><blockquote><p>PS:基本上数据结构里面都有，这里不再赘述。主要讲解图的遍历</p></blockquote><h4 id="DFS">DFS</h4><p>DFS是深度优先搜索，在之前讲搜索的时候就已经接触过DFS了(请参考之前蓝桥杯系列的博客)，现在把DFS融入到具体的图中，而不是隐含的图中。回忆一下DFS的核心思想：“<strong>一条路走到黑，走过的路不再走</strong>”。一般都是通过递归实现的</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">bitset&lt;N&gt; vis;<span class="comment">//vis[i] = ture 说明i点已经走过</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    vis[x] = <span class="literal">true</span>;<span class="comment">//打上标记</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;y:g[x])</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(vis[y])</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">            <span class="built_in">dfs</span>(y);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="BFS">BFS</h3><p>BFS是宽度优先搜索，其核心思想是： <strong>一层一往外走，每个点只走一次</strong>.通常用于求边权想等情况下的最短距离</p><p>一般通过队列实现</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">bitset&lt;N&gt;vis;<span class="comment">//vis[i] = true说明i点已经走过</span></span><br><span class="line">queue&lt;<span class="type">int</span>&gt;q;<span class="comment">//q表示待扩展的点队列</span></span><br><span class="line"><span class="keyword">while</span>(q.<span class="built_in">size</span>()) <span class="comment">//只要队列不为空</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> x = q.<span class="built_in">front</span>();</span><br><span class="line">    q.<span class="built_in">pop</span>();</span><br><span class="line">    <span class="keyword">if</span>(vis[x])</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    vis[x] = <span class="literal">true</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;y:g[x])</span><br><span class="line">    &#123;</span><br><span class="line">        q.<span class="built_in">push</span>(y);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><p><a href="https://www.lanqiao.cn/problems/3891/learning/?page=1&amp;first_category_id=1&amp;problem_id=3891">1.帮派弟位 - 蓝桥云课</a></p></li><li><p><a href="https://www.lanqiao.cn/problems/3352/learning/?page=1&amp;first_category_id=1&amp;problem_id=3352">1.可行路径的方案数 - 蓝桥云课</a></p></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_26">点击此处</a></p><h3 id="最小生成树">最小生成树</h3><p>【概念】：最小生成树是指，对于一个连通图，剔除其中一部分边，而保留一部分边，使得<strong>剩下的部分构成一棵树，并且这棵树的所有边的权值之和最小</strong>。最小生成树所处理的图的边权一般是不相等的，否则意义不大。数据结构中实现的方法就是kruskal算法和prim算法。</p><p>最小生成树(MST)的性质如下</p><ol><li>MST的边权和是所有生成树中最小的</li><li>MST的最大边权是所有生成树中最小的</li></ol><p>【实现】</p><ol><li>kruskal算法</li></ol><p>其核心思想是贪心,1.将所有边按照边权排序。2.从小到大遍历所有边(u,v)，如果(u,v)已经连通就跳过，否则就选中(u,v)，将它俩相连。在第二步中的连通性判断需要用到我们之前学过的并查集。示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span><span class="number">+9</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Edge</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> x, y, c;</span><br><span class="line">    <span class="type">bool</span> <span class="keyword">operator</span> &lt; (<span class="type">const</span> Edge &amp;u) <span class="type">const</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> c &lt; u.c; </span><br><span class="line">    &#125; </span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> pre[N];</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">root</span><span class="params">(<span class="type">int</span> x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> pre[x] = (pre[x] == x ? x : <span class="built_in">root</span>(pre[x]));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> n, m;</span><br><span class="line">    cin &gt;&gt; n &gt;&gt; m;</span><br><span class="line">    vector&lt;Edge&gt; es;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> x, y, c;</span><br><span class="line">        cin &gt;&gt; x &gt;&gt; y &gt;&gt; c;</span><br><span class="line">        es.<span class="built_in">push_back</span>(&#123;x, y, c&#125;); </span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="built_in">sort</span>(es.<span class="built_in">begin</span>(), es.<span class="built_in">end</span>());</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        pre[i] = i;  </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span>&amp; e : es)  </span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> x = e.x;</span><br><span class="line">        <span class="type">int</span> y = e.y;</span><br><span class="line">        <span class="type">int</span> c = e.c;</span><br><span class="line">        <span class="keyword">if</span>(<span class="built_in">root</span>(x) == <span class="built_in">root</span>(y))</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        ans = <span class="built_in">max</span>(ans, c);</span><br><span class="line">        pre[<span class="built_in">root</span>(x)] = <span class="built_in">root</span>(y);</span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; ans &lt;&lt; <span class="string">&quot;\n&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">solve</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>Prim算法</li></ol><p>Prim算法采用集合的思想，维护一个mst集合，里面存储已经在最小生成树中的点。</p><ol><li>从起点(一般为1号点)出发，每次找出<strong>不在mst中且d[最小的点x,d[x]就是选中的那条边的边权</strong>。</li><li>将点x加入到mst中，并更新其所有出点y，更新d[y]=min(d[y],w);其中w为x-&gt;y的距离</li><li>如果d[y]变小了，就加入到优先队列中作为可能的拓展点。这个mst集合我们<strong>用bool数组或bitset</strong>来实现即可。</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span> + <span class="number">9</span>;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll; <span class="comment">// 添加 long long 的别名</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Edge</span></span><br><span class="line">&#123;</span><br><span class="line">    ll x, c;</span><br><span class="line">    <span class="type">bool</span> <span class="keyword">operator</span> &lt; (<span class="type">const</span> Edge &amp;u) <span class="type">const</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> c == u.c ? x &gt; u.x : c &gt; u.c; <span class="comment">// 按 c 从大到小排序，若 c 相同则按 x 从大到小排序</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">vector&lt;Edge&gt; g[N]; <span class="comment">// 邻接表存储图</span></span><br><span class="line">ll d[N]; <span class="comment">// 存储每个节点的最小边权</span></span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">prim</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    priority_queue&lt;Edge&gt; pq;</span><br><span class="line">    bitset&lt;N&gt; vis; </span><br><span class="line"></span><br><span class="line">    <span class="built_in">fill</span>(d, d + N, LLONG_MAX); <span class="comment">// 初始化 d 数组为最大值</span></span><br><span class="line">    d[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">    pq.<span class="built_in">push</span>(&#123;<span class="number">1</span>, d[<span class="number">1</span>]&#125;);</span><br><span class="line"></span><br><span class="line">    ll res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span> (!pq.<span class="built_in">empty</span>())</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> x = pq.<span class="built_in">top</span>().x;</span><br><span class="line">        pq.<span class="built_in">pop</span>();</span><br><span class="line">        <span class="keyword">if</span> (vis[x]) </span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        vis[x] = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">        res = <span class="built_in">max</span>(res, d[x]); <span class="comment">// 更新最大边权</span></span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span> &amp;e : g[x]) </span><br><span class="line">        &#123;</span><br><span class="line">            <span class="type">int</span> y = e.x;</span><br><span class="line">            ll w = e.c;</span><br><span class="line">            <span class="keyword">if</span> (vis[y])</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (w &lt; d[y])</span><br><span class="line">            &#123;</span><br><span class="line">                d[y] = w;</span><br><span class="line">                pq.<span class="built_in">push</span>(&#123;y, d[y]&#125;);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    cin &gt;&gt; n &gt;&gt; m; <span class="comment">// 输入节点数和边数</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        ll x, y, w;</span><br><span class="line">        cin &gt;&gt; x &gt;&gt; y &gt;&gt; w;</span><br><span class="line">        g[x].<span class="built_in">push_back</span>(&#123;y, w&#125;); <span class="comment">// 无向图，双向加边</span></span><br><span class="line">        g[y].<span class="built_in">push_back</span>(&#123;x, w&#125;);</span><br><span class="line">    &#125;</span><br><span class="line">    cout &lt;&lt; <span class="built_in">prim</span>() &lt;&lt; endl; <span class="comment">// 输出最大边权</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3322/learning/?page=1&amp;first_category_id=1&amp;problem_id=3322">1.旅行销售员 - 蓝桥云课</a></li></ul><p>最小生成树的典型例题，用模板套用即可。我的解法是用kruskal</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_26">点击此处</a></p><h3 id="拓扑排序">拓扑排序</h3><p>【概念】：拓扑排序是一种针对“有向无环图”的算法，用于解决一些有“依赖关系”的问题。拓扑排序保证了当处理到某个点时，其所有的入点都已经处理过了。比如6的节点被2与4节点指向，而通过拓扑排序可以实现在处理6节点之前点2与4都被处理过了。</p><p>拓扑排序不一定是“唯一”的，只要满足拓扑关系即可，当然在算法中要保证同样的输入要得到同样的输出。</p><p>【实现】：拓扑排序一般借助queue(队列)，使用类似BFS实现，先处理出每个点的入度，这个在读入边的时候处理。图一般用邻接表建立。在枚举边x-&gt;y的时候，可以进行状态转移，于是可以和动态规划结合起来。这样的DP也叫做DAG-DP（有向无环图上的动态规划）。状态转移一般只发生在枚举所有边的时候</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">topo</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">queue&lt;<span class="type">int</span>&gt; q;</span><br><span class="line"><span class="comment">//将所有入度为0的点加入到队列中</span></span><br><span class="line"><span class="keyword">for</span>(itn i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(!ind[i])</span><br><span class="line">&#123;</span><br><span class="line">q.<span class="built_in">push</span>(i);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span>(q.<span class="built_in">size</span>())</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//取出队头的点x,此时它的入度一定为0</span></span><br><span class="line"><span class="type">int</span> x = q.<span class="built_in">front</span>();</span><br><span class="line">q.<span class="built_in">pop</span>();</span><br><span class="line"><span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;y:g[x]) </span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//处理边x-&gt;y</span></span><br><span class="line">ind[y]  --;<span class="comment">//处理完成后y的入度--</span></span><br><span class="line"><span class="keyword">if</span>(!ind[y]) </span><br><span class="line">&#123;</span><br><span class="line">q.<span class="built_in">push</span>(y);<span class="comment">//如果y入度为0，说明y的所有入点已经处理完成直接入队 </span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> m;</span><br><span class="line">cin&gt;&gt;m;</span><br><span class="line"><span class="keyword">while</span>(m--)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//新增一条u-&gt;v的边</span></span><br><span class="line"><span class="type">int</span> u,v;</span><br><span class="line">cin&gt;&gt;u&gt;&gt;v;</span><br><span class="line">ind[v] ++;<span class="comment">//V的入度+1; </span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1337/learning/?page=1&amp;first_category_id=1&amp;problem_id=1337">1.走多远 - 蓝桥云课</a></li></ul><p>设状态dp[i]表示i点距离某一个起点的最远距离，状态转移的方向就是拓扑的顺序。假如存在一条边x-&gt;y，则有dp[y]=max(dp[y], dp[x] + 1);初始化时dp[i] = 0;</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_26">点击此处</a></p><h3 id="最短路径问题">最短路径问题</h3><blockquote><p>PS：这个也是数据结构中的知识点，最令学子闻风丧胆的就是Floyd算法和Dijkstra算法</p></blockquote><h4 id="Floyd算法">Floyd算法</h4><p>【概念】：Floyd算法是一种求解 “多源最短路” 问题的算法。在Floyd算法中，图一般用邻接矩阵存储，边权可正可负（但不允许负环），利用动态规划的思想，逐步求解出任意两点之间的最短距离。我们需要准备的东西很少，只要一个d数组：<code>int d[N][N][N]</code>，初始为无穷。<code>d[k][i][j]</code><strong>表示路径（除去起点和终点）中编号最大的点编号&lt;=k的情况下，点到点j的最短距离</strong>。但是实际上k这一维度是可以优化掉的，所以直接用<code>int d[N][N]</code>;<code>d[i][j]</code>表示考虑到当前情况下，点到点j的最短距离。整体代码非常简单，初学时只需要学会怎么写，怎么用就行，无需过度理解其含义。</p><p>核心部分如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//注意k作为中转点，必须放在最外层</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> k = <span class="number">1</span>;k&lt;=n;k++)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">for</span>(itn j = <span class="number">1</span>;j&lt;=n;j++)</span><br><span class="line">        &#123;</span><br><span class="line">            d[i][j] = <span class="built_in">min</span>(d[i][j],d[i][k]+d[k][j]);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看到算法的复杂度较高，所以一般在数据量小的情况下才使用Floyd算法。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1121/learning/?page=1&amp;first_category_id=1&amp;problem_id=1121">1.蓝桥公园 - 蓝桥云课</a></li></ul><p>这个就是Floyd算法题的经典形式</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_26">点击此处</a></p><h4 id="Dijkstra算法">Dijkstra算法</h4><p>【概念】：Dijkstra算法是一种高效的处理非负边权的“单源最短路”问题的算法，例如求出所有点距离源点1的距离。可以说Dijkstra是最重要的图论算法之一。Dijkstra算法利用了贪心和动态规划的思想，也有多个版本：朴素版、堆优化版，这里直接<strong>讲解Dijkstra算法的堆优化版本(priority_queue优先队列实现，最常用，最高效)</strong>。</p><p>【实现】</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e7</span> + <span class="number">9</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> d[N]; <span class="comment">// d[i] 表示点 i 距离源点的最短距离</span></span><br><span class="line">bitset&lt;N&gt; vis; <span class="comment">// 表示某个点是否走过，按照迪杰斯特拉的贪心思想，第一次走到的时候得到的距离一定是最短距离，所以一个点不能走第二次</span></span><br><span class="line">vector&lt;pair&lt;<span class="type">int</span>, <span class="type">int</span>&gt;&gt; g[N]; <span class="comment">// 邻接表存储图，g[x] 存储从 x 出发的边，pair&lt;y, dw&gt; 表示 x-&gt;y 的边权为 dw</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Node</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> x, w; <span class="comment">// x 表示点编号，w 表示源点到 x 的最短距离</span></span><br><span class="line">    <span class="type">bool</span> <span class="keyword">operator</span> &lt; (<span class="type">const</span> Node &amp;u) <span class="type">const</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> w == u.w ? x &lt; u.x : w &gt; u.w; <span class="comment">// 修正：按照 w 升序，在优先级队列中 w 最小的作为堆顶</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">priority_queue&lt;Node&gt; pq;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 迪杰斯特拉算法的堆优化</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Dijkstra</span><span class="params">(<span class="type">int</span> st)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="built_in">fill</span>(d, d + N, INT_MAX); <span class="comment">// 初始化 d 数组为最大值</span></span><br><span class="line">    d[st] = <span class="number">0</span>; <span class="comment">// 源点到源点的距离为 0</span></span><br><span class="line">    pq.<span class="built_in">push</span>(&#123;st, d[st]&#125;); <span class="comment">// 将源点加入优先队列</span></span><br><span class="line">    <span class="keyword">while</span> (!pq.<span class="built_in">empty</span>()) <span class="comment">// 只要队列不为空</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">auto</span> [x, w] = pq.<span class="built_in">top</span>();</span><br><span class="line">        pq.<span class="built_in">pop</span>(); <span class="comment">// 取出队头元素</span></span><br><span class="line">        <span class="keyword">if</span> (vis[x])</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>; <span class="comment">// 如果走过直接跳过</span></span><br><span class="line">        &#125;</span><br><span class="line">        vis[x] = <span class="literal">true</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">const</span> <span class="keyword">auto</span> &amp;[y, dw] : g[x]) <span class="comment">// 遍历从 x 出发的边，x-&gt;y 边权为 dw</span></span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">if</span> (d[x] + dw &lt; d[y]) <span class="comment">// 如果通过 x 到 y 的距离更短</span></span><br><span class="line">            &#123;</span><br><span class="line">                d[y] = d[x] + dw; <span class="comment">// 更新 y 的最短距离</span></span><br><span class="line">                pq.<span class="built_in">push</span>(&#123;y, d[y]&#125;); <span class="comment">// 将 y 加入优先队列</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> n, m, st;</span><br><span class="line">    cin &gt;&gt; n &gt;&gt; m &gt;&gt; st; <span class="comment">// 输入节点数、边数和源点</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= m; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="type">int</span> x, y, w;</span><br><span class="line">        cin &gt;&gt; x &gt;&gt; y &gt;&gt; w;</span><br><span class="line">        g[x].<span class="built_in">push_back</span>(&#123;y, w&#125;); <span class="comment">// 添加有向边 x-&gt;y，边权为 w</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">Dijkstra</span>(st); <span class="comment">// 调用 Dijkstra 算法</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (d[i] == INT_MAX)</span><br><span class="line">            cout &lt;&lt; <span class="string">&quot;INF &quot;</span>; <span class="comment">// 如果不可达，输出 INF</span></span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            cout &lt;&lt; d[i] &lt;&lt; <span class="string">&quot; &quot;</span>; <span class="comment">// 输出源点到每个点的最短距离</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1122/learning/?page=1&amp;first_category_id=1&amp;problem_id=1122">1.蓝桥王国 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_26">点击此处</a></p><h4 id="BellmanFord算法">BellmanFord算法</h4><p>【概念】：它<strong>可以计算负权图的单源最短路</strong>，且可以判断负环，但是时间复杂度较高，是O(nm)。</p><p>【实现】：松驰 用这条边去更新源点至到出点的最短路径。用每条边去做松弛操作，进行n-1轮松弛，因为在n个点的图中一条路径最由n-1条边组成，如果n-1轮松弛之后还能松弛，就说明存在负权环，否则就可以得到单源最短路。</p><p>代码示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"><span class="type">const</span> ll inf = <span class="number">1e18</span>;</span><br><span class="line"></span><br><span class="line">ll h[N];<span class="comment">//h[N]表示点0到x的最短距离</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Bellman_Ford</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//初始化h[]为无穷</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        h[i] = inf;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//h[0] = 0;可以忽略</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">//一共n个点，所以松弛n-1次，i用于计数</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;n;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">//枚举所有的边,尝试用这条边去松弛点x</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;[x,y,w]:es)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">if</span>(h[x] == inf)</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">//如果可以通过这条边可以松弛</span></span><br><span class="line">            <span class="keyword">if</span>(h[x]+w&lt;h[y])</span><br><span class="line">            &#123;</span><br><span class="line">                h[y] = h[x]+w;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//判断是否存在负权环</span></span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;[x,y,z]:es)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(h[x] == inf)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//如果还有边可以松弛，那么说明存在负环返回false</span></span><br><span class="line">        <span class="keyword">if</span>(h[x] + w&lt;h[y])</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//不存在负环</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Johnson算法">Johnson算法</h4><p>【例题引入】：题目背景是求解稀疏图的全源最短路，点的个数<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≤</mo><msup><mn>10</mn><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">n \leq 10^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span>，边数<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>≤</mo><mn>2</mn><mo>×</mo><msup><mn>10</mn><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">m \leq 2 \times 10^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span>，典型的稀疏图。</p><p>【实现】：</p><ol><li>设置超级源点，用BellmanFord求单源最短路得到“势能”</li><li>在势能帮助下重新设置每条边的权重</li><li>跑n次Dijkstra算法计算出所有点的单源最短路，即得到了全源最短路</li></ol><p>re-weight，顾名思义就是重新调整每条边的权重，对于一个图，我们先建立一个&quot;SuperSourceNode”（超级源点），我们用0号节点表示，并且将其与所有点连接起来，边权为0。接下来用Bellman-Ford算法计算出超级源点的单源最短路，这个是很简单的。</p><p>好，假如不存在负环，现在我们就得到了一个h[]数组对吧，接下来我们令每条边的权重w(u,v)=w(u,v)+h[u]一h[v]。这样一定可以使得所有边权都为正权，假如w(u,v)&lt;0，那么必然有h[u]+w(u,v)≥h[v]，于是有w(u,v)+h[u]-h[v]≥0。</p><p>在此基础上去对每一个点跑Dijkstra算法，即可求得对于每一个点的单源最短路径，而求出来的这个距离d(u,v)实际上是进行了偏移之后的，要还原为真实的距离还要令f(u,v)=d(u,v)-h[u]+h[v]。</p><p>注意我们第一次的数组h1，为什么不直接用d来表示呢？因为在物理中的含义是“势能”，我们将一个物理意义挪用到信息学中，可以形象的解释h数组的意义。</p><p>我们可以发现，如果存在一条路径：u-&gt;x1-&gt;x2-&gt;…-&gt;xk-&gt;v，那么就有：</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi>h</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">]</mo><mo stretchy="false">]</mo><mo>+</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">]</mo><mo stretchy="false">]</mo><mo>+</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>+</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>k</mi></msub><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>+</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mi>k</mi></msub><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">d(u,v) = [w(u,x_1)+h[u]-h[x_1]]+[w(x_1,x_2)+h[x_1]-h[x_2]]+...+[w(x_k,v)+h[x_k]-h[v]]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]]</span></span></span></span></span></p><p>稍微做个变换可以得到：</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi>w</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">]</mo><mo>+</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>+</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>k</mi></msub><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo stretchy="false">]</mo><mo>+</mo><mo stretchy="false">[</mo><mi>h</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">]</mo><mo>+</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>+</mo><mi>h</mi><mo stretchy="false">[</mo><msub><mi>x</mi><mi>k</mi></msub><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">d(u,v) = [w(u,x_1)+w(x_1,x_2)]+...+[w(x_k,v)]+[h[u]-h[x_1]-h[x_2]+...+h[x_k]-h[v]]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]]</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>+</mo><mi>w</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo stretchy="false">)</mo><mo stretchy="false">]</mo><mo>+</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>+</mo><mo stretchy="false">[</mo><mi>w</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>k</mi></msub><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo stretchy="false">]</mo><mo>+</mo><mi>h</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">d(u,v) = [w(u,x_1)+w(x_1,x_2)]+...+[w(x_k,v)]+h[u]-h[v]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>=</mo><mi>f</mi><mo stretchy="false">(</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo stretchy="false">)</mo><mo>+</mo><mi>h</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo>−</mo><mi>h</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">d(u,v) = f(u,v) + h[u] - h[v]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span></span></span></span></span></p><p>其中f(u,v)为u,v的真实距离。所以真实距离是我们计算出的d(u,v)-h[u]+h[v]。注意这个真实距离可能是负数，并且如果你要判断两点不存在路径的话，应该判断d和f，就像在dijkstra中一样。</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_27">点击此处</a></p><hr><h2 id="计算几何">计算几何</h2><h3 id="点和线之间的关系">点和线之间的关系</h3><p>【概念】：点在二维平面坐标系下表示为(x,y)，所以一般来说，依据题目条件的不同，我们需要一个pair或者结构体来存储点。具体的类型依据题目而定，一般是int/longlong/double（不建议）</p><p>【例题】：常见的出题形式基本上和出数学题类似，只不过要求你用计算机语言实现，所以是否能够理解其中的数学关系至关重要。</p><p><strong>判断一个点在直线的哪一边</strong>：因为B在直线上，所以对于<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mi>b</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>b</mi></msub></mrow><annotation encoding="application/x-tex">x_b,y_b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>而言，满足<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mi>b</mi></msub><mo>=</mo><mi>k</mi><mo>×</mo><msub><mi>x</mi><mi>b</mi></msub><mo>+</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">y_b = k \times x_b+b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span></span></span></span> 假设A在直线的上方，所以如果过A做<br>一条竖直向下的直线l2，则一定会存在一个交点D，满足<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mi>d</mi></msub><mo>=</mo><mi>k</mi><mo>×</mo><msub><mi>x</mi><mi>d</mi></msub><mo>+</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">y_d = k \times x_d +b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span></span></span></span> 又因为A与D的x坐标相等，A的y坐标更大，所以对于A而言，满足<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mi>a</mi></msub><mo>&gt;</mo><mi>k</mi><mo>×</mo><msub><mi>x</mi><mi>a</mi></msub><mo>+</mo><mi>b</mi></mrow><annotation encoding="application/x-tex">y_a&gt;k \times x_a +b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span></span></span></span></p><p><strong>点到线的垂足</strong>：</p><p><strong>方法一:</strong>假设需要求的点坐标是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>E</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>e</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>e</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">E(x_e,y_e)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>,直线方程<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mi>x</mi><mo>+</mo><mi>B</mi><mi>y</mi><mo>+</mo><mi>C</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">Ax+By+C=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>,可以直接假设垂足的位置<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>f</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>f</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F(x_f,y_f)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>, 考虑到原直线<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>l</mi></mrow><annotation encoding="application/x-tex">l</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span></span></span></span>的斜率是一<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mi mathvariant="normal">/</mi><mi>B</mi></mrow><annotation encoding="application/x-tex">A/B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">A</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span>,则直线EF的斜率是其倒数，也就是B/A。根据已知的条件(过一点和斜率),可以确定直线EF的表达式为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>A</mi><mi>y</mi><mo>−</mo><mi>B</mi><mi>x</mi><mo>−</mo><mi>A</mi><msub><mi>y</mi><mi>e</mi></msub><mo>+</mo><mi>B</mi><msub><mi>x</mi><mi>e</mi></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">Ay-Bx-Ay_{e}+Bx_{e}=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">A</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>。通过联立两个直线可以获得交点坐标<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>F</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>f</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>f</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F(x_f,y_f)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mi>f</mi></msub><mo>=</mo><mfrac><mrow><mo>−</mo><mi>A</mi><mi>B</mi><msub><mi>y</mi><mi>e</mi></msub><mo>−</mo><mi>A</mi><mi>C</mi><mo>+</mo><msup><mi>B</mi><mn>2</mn></msup><msub><mi>x</mi><mi>e</mi></msub></mrow><mrow><msup><mi>A</mi><mn>2</mn></msup><mo>+</mo><msup><mi>B</mi><mn>2</mn></msup></mrow></mfrac></mrow><annotation encoding="application/x-tex">x_f=\frac{-ABy_e-AC+B^2x_e}{A^2+B^2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4734em;vertical-align:-0.4033em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.07em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>     <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>y</mi><mi>f</mi></msub><mo>=</mo><mfrac><mrow><msup><mi>A</mi><mn>2</mn></msup><msub><mi>y</mi><mi>e</mi></msub><mo>−</mo><mi>A</mi><mi>B</mi><msub><mi>x</mi><mi>e</mi></msub><mo>−</mo><mi>B</mi><mi>C</mi></mrow><mrow><msup><mi>A</mi><mn>2</mn></msup><mo>+</mo><msup><mi>B</mi><mn>2</mn></msup></mrow></mfrac></mrow><annotation encoding="application/x-tex">y_f=\frac{A^2y_e-ABx_e-BC}{A^2+B^2}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4734em;vertical-align:-0.4033em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.07em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">BC</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>即为垂足坐标。只需计算E(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mi>e</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>e</mi></msub></mrow><annotation encoding="application/x-tex">x_e,y_e</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>)和F(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mi>f</mi></msub><mo separator="true">,</mo><msub><mi>y</mi><mi>f</mi></msub></mrow><annotation encoding="application/x-tex">x_f,y_f</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>)的距离即可获得距离。最终得到距离计算公式<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>i</mi><mi>s</mi><mo>=</mo><msqrt><mfrac><mrow><mo stretchy="false">(</mo><mi>A</mi><msub><mi>x</mi><mi>e</mi></msub><mo>+</mo><mi>B</mi><msub><mi>y</mi><mi>e</mi></msub><mo>+</mo><mi>C</mi><msup><mo stretchy="false">)</mo><mn>2</mn></msup></mrow><mrow><msup><mi>A</mi><mn>2</mn></msup><mo>+</mo><msup><mi>B</mi><mn>2</mn></msup></mrow></mfrac></msqrt></mrow><annotation encoding="application/x-tex">dis = \sqrt{\frac{(Ax_e + By_e + C)^2}{A^2 + B^2}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">i</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.84em;vertical-align:-0.5517em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2883em;"><span class="svg-align" style="top:-3.8em;"><span class="pstrut" style="height:3.8em;"></span><span class="mord" style="padding-left:1em;"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">A</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span><span class="mclose mtight"><span class="mclose mtight">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.2483em;"><span class="pstrut" style="height:3.8em;"></span><span class="hide-tail" style="min-width:1.02em;height:1.88em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.88em" viewbox="0 0 400000 1944" preserveaspectratio="xMinYMin slice"><path d="M983 90l0 -0c4,-6.7,10,-10,18,-10 H400000v40H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744c-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30c26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5c53.7,-170.3,84.5,-266.8,92.5,-289.5zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.5517em;"><span></span></span></span></span></span></span></span></span></p><p><strong>方法二</strong>:设直线 L 的方程为 Ax + By + C = 0，点 P 的坐标为 (x₀, y₀)，则点 P 到直线 L 的距离就是：<br><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi mathvariant="normal">∣</mi><mi>A</mi><msub><mi>x</mi><mn>0</mn></msub><mo>+</mo><mi>B</mi><msub><mi>y</mi><mn>0</mn></msub><mo>+</mo><mi>C</mi><mi mathvariant="normal">∣</mi></mrow><msqrt><mrow><msup><mi>A</mi><mn>2</mn></msup><mo>+</mo><msup><mi>B</mi><mn>2</mn></msup></mrow></msqrt></mfrac></mrow><annotation encoding="application/x-tex">\frac{|Ax_0+By_0+C|}{\sqrt{A^2+B^2}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.548em;vertical-align:-0.538em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.5445em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord sqrt mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9221em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mtight" style="padding-left:0.833em;"><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-2.8821em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail mtight" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewbox="0 0 400000 1080" preserveaspectratio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1179em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∣</span><span class="mord mathnormal mtight">A</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span><span class="mord mtight">∣</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.538em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> 。同理可知，当P (x₀,y₀)，直线的解析式为y=kx+b时，则点P到直线L的距离为：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mrow><mi mathvariant="normal">∣</mi><mi>k</mi><msub><mi>x</mi><mn>0</mn></msub><mo>−</mo><msub><mi>y</mi><mn>0</mn></msub><mo>+</mo><mi>b</mi><mi mathvariant="normal">∣</mi></mrow><msqrt><mrow><mn>1</mn><mo>+</mo><msup><mi>k</mi><mn>2</mn></msup></mrow></msqrt></mfrac></mrow><annotation encoding="application/x-tex">\frac{|kx_0-y_0+b|}{\sqrt{1+k^2}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.548em;vertical-align:-0.538em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.5445em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord sqrt mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9221em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mtight" style="padding-left:0.833em;"><span class="mord mtight">1</span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-2.8821em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail mtight" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewbox="0 0 400000 1080" preserveaspectratio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1179em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∣</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mathnormal mtight">b</span><span class="mord mtight">∣</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.538em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>可以先计算出直线斜率 k，再套用第二个公式即可。在计算几何中，斜率是非常重要的，但是当直线 BC 是为竖直时，斜率为无穷，此时斜率法处理，需要用到<strong>向量</strong>。</p><p><strong>方法三</strong>：设点A(x1, y1)，点B(x2, y2)，点C(x3, y3)，求点A到直线BC的距离。我们可以知道，向量AB=(x2-x1, y2-y1)，向量AC=(x3-x1, y3-y1)。<br><strong>向量叉乘(这是线性代数的知识)可以得到两个向量构成的平行四边形的面积</strong>，通过这个关系得到点到直线的距离。  <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo>=</mo><mfrac><mrow><mi mathvariant="normal">∣</mi><mover accent="true"><mrow><mi>A</mi><mi>B</mi></mrow><mo>⃗</mo></mover><mo>×</mo><mover accent="true"><mrow><mi>A</mi><mi>C</mi></mrow><mo>⃗</mo></mover><mi mathvariant="normal">∣</mi></mrow><mrow><mi mathvariant="normal">∣</mi><mover accent="true"><mrow><mi>B</mi><mi>C</mi></mrow><mo>⃗</mo></mover><mi mathvariant="normal">∣</mi></mrow></mfrac></mrow><annotation encoding="application/x-tex">d = \frac{|{\vec{AB}} \times {\vec{AC}}|}{|\vec{BC}|}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.8229em;vertical-align:-0.6614em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1614em;"><span style="top:-2.5136em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∣</span><span class="mord accent mtight"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9663em;"><span style="top:-2.714em;"><span class="pstrut" style="height:2.714em;"></span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">BC</span></span></span><span style="top:-2.9663em;"><span class="pstrut" style="height:2.714em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay mtight" style="height:0.714em;width:0.471em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.471em" height="0.714em" style="width:0.471em" viewbox="0 0 471 714" preserveaspectratio="xMinYMin"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z"/></svg></span></span></span></span></span></span></span><span class="mord mtight">∣</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∣</span><span class="mord mtight"><span class="mord accent mtight"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9663em;"><span style="top:-2.714em;"><span class="pstrut" style="height:2.714em;"></span><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span><span style="top:-2.9663em;"><span class="pstrut" style="height:2.714em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay mtight" style="height:0.714em;width:0.471em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.471em" height="0.714em" style="width:0.471em" viewbox="0 0 471 714" preserveaspectratio="xMinYMin"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z"/></svg></span></span></span></span></span></span></span></span><span class="mbin mtight">×</span><span class="mord mtight"><span class="mord accent mtight"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9663em;"><span style="top:-2.714em;"><span class="pstrut" style="height:2.714em;"></span><span class="mord mtight"><span class="mord mathnormal mtight">A</span><span class="mord mathnormal mtight" style="margin-right:0.07153em;">C</span></span></span><span style="top:-2.9663em;"><span class="pstrut" style="height:2.714em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay mtight" style="height:0.714em;width:0.471em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.471em" height="0.714em" style="width:0.471em" viewbox="0 0 471 714" preserveaspectratio="xMinYMin"><path d="M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z"/></svg></span></span></span></span></span></span></span></span><span class="mord mtight">∣</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.6614em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>通俗地讲，这个公式可以转化为(于是就没有考虑斜率)：  <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo>=</mo><mfrac><mrow><mi mathvariant="normal">∣</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mn>2</mn></msub><mo>−</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>3</mn></msub><mo>−</mo><msub><mi>y</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>−</mo><mo stretchy="false">(</mo><msub><mi>x</mi><mn>3</mn></msub><mo>−</mo><msub><mi>x</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>2</mn></msub><mo>−</mo><msub><mi>y</mi><mn>1</mn></msub><mo stretchy="false">)</mo><mi mathvariant="normal">∣</mi></mrow><msqrt><mrow><mo stretchy="false">(</mo><msub><mi>x</mi><mn>3</mn></msub><mo>−</mo><msub><mi>x</mi><mn>2</mn></msub><msup><mo stretchy="false">)</mo><mn>2</mn></msup><mo>+</mo><mo stretchy="false">(</mo><msub><mi>y</mi><mn>3</mn></msub><mo>−</mo><msub><mi>y</mi><mn>2</mn></msub><msup><mo stretchy="false">)</mo><mn>2</mn></msup></mrow></msqrt></mfrac></mrow><annotation encoding="application/x-tex">d = \frac{|(x_2 - x_1) \times (y_3 - y_1) - (x_3 - x_1) \times (y_2 - y_1)|}{\sqrt{(x_3 - x_2)^2 + (y_3 - y_2)^2}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.8396em;vertical-align:-0.8296em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.4642em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord sqrt mtight"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0369em;"><span class="svg-align" style="top:-3.4286em;"><span class="pstrut" style="height:3.4286em;"></span><span class="mord mtight" style="padding-left:1.19em;"><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight"><span class="mclose mtight">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-3.0089em;"><span class="pstrut" style="height:3.4286em;"></span><span class="hide-tail mtight" style="min-width:0.853em;height:1.5429em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.5429em" viewbox="0 0 400000 1080" preserveaspectratio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4197em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∣</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span><span class="mbin mtight">×</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span><span class="mbin mtight">−</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span><span class="mbin mtight">×</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0359em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span><span class="mord mtight">∣</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8296em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/1242/learning/?page=1&amp;first_category_id=1&amp;problem_id=1242">1.点和线段关系 - 蓝桥云课</a></li></ul><p>其实这一题可以直接用向量法秒掉的( •̀ ω •́ )✧</p><ul><li><a href="https://www.lanqiao.cn/problems/1240/learning/?page=1&amp;first_category_id=1&amp;problem_id=1240">1.点和直线关系 - 蓝桥云课</a></li></ul><p>同理可以用数学关系解答，如果读者会使用向量法的话可以更加轻松解决。</p><ul><li><a href="https://www.lanqiao.cn/problems/1285/learning/?page=1&amp;first_category_id=1&amp;problem_id=1285">1.点到线段距离 - 蓝桥云课</a></li></ul><p>也是同理</p><ul><li><a href="https://www.lanqiao.cn/problems/1286/learning/?page=1&amp;first_category_id=1&amp;problem_id=1286">1.点到直线距离 - 蓝桥云课</a></li></ul><p>这一题用向量法求解会很方便，而且可以不用考虑线段斜率为无穷大的情况(当然特殊处理也不是不行)。本题目的实现代码链接如下 <a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_28">点击此处</a></p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_27">点击此处</a></p><h3 id="点和点之间的关系">点和点之间的关系</h3><p>【概念】：平面上两点距离一般可分为<strong>欧几里得距离</strong>和<strong>曼哈顿距离</strong>。现在在二维平面上有两个点(x1,y1),(x2,y2).欧几里得距离：即常见的两点直线连线距离，通过<strong>勾股定理</strong>计算。d=sqrt(x1-x2)2+(y1-y2)2).曼哈顿距离：<strong>两点的x差值的绝对值与y的差值的绝对值之和</strong> 即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><msub><mi>x</mi><mn>1</mn></msub><mo>−</mo><msub><mi>x</mi><mn>2</mn></msub><mi mathvariant="normal">∣</mi><mo>+</mo><mi mathvariant="normal">∣</mi><msub><mi>y</mi><mn>1</mn></msub><mo>−</mo><msub><mi>y</mi><mn>2</mn></msub><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">|x_1-x_2|+|y_1-y_2|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span></span></span></span>，这个距离通常用在整数点上，因为这个距离对于整数点来说计算结果总是整数，而欧几里得距离会产生浮点。当然，在某些时候为了避免浮点误差(比如在C++中让eps = 1e-9,虽然趋近于0，但是不是真正的零)，如果可以不进行开方的情况，我们会使用欧几里得距离的平方来处理。</p><p>【实现】：</p><ol><li>求两点的曼哈顿距离，一般用于整数点</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">dist</span><span class="params">(<span class="type">int</span> x1,<span class="type">int</span> y1,<span class="type">int</span> x2,<span class="type">int</span> y2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> dx = <span class="built_in">abs</span>(x1-x2);</span><br><span class="line">    <span class="type">int</span> dy = <span class="built_in">abs</span>(y1-y2);<span class="comment">//处理出差值方便编写代码，</span></span><br><span class="line">    <span class="keyword">return</span> dx+dy;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="2"><li>求两点欧几里得距离</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">double</span> <span class="title">dist</span><span class="params">(<span class="type">double</span> x1,<span class="type">double</span> y1,<span class="type">double</span> x2,<span class="type">double</span> y2)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">double</span> dx = x1-x2;</span><br><span class="line">    <span class="type">double</span> dy = y1-y2;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">sqrt</span>(dx*dx+dy*dy);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="圆">圆</h3><p>主要就是求圆的周长和面积，其代码实现很简单。需要注意的在C++中，计算<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>π</mi></mrow><annotation encoding="application/x-tex">\pi</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">π</span></span></span></span>有一种准确的方法，就是double pi = acos(-1).在Python中可以导入math直接用pi。</p><p><strong>圆之间的关系</strong></p><ol><li>两圆相交：dist&lt;r1+r2</li><li>两圆相切：dist = r1+r2.注意如果变量类型是浮点数好的话要<strong>设置一定的偏差量eps,以免浮点误差带来的影响</strong>。</li><li>两圆相离：dist&gt;r1+r2</li></ol><h3 id="三角形">三角形</h3><p>一般三角形的面积——海伦公式</p><p>【概念】：已知一个三角形的三条边分别为a,b,c,设p=(a+b+c)/2,三角形面积为s,则有：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mo>=</mo><msqrt><mrow><mi>p</mi><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mi>a</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mi>b</mi><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mi>c</mi><mo stretchy="false">)</mo></mrow></msqrt></mrow><annotation encoding="application/x-tex">s = \sqrt{p(p-a)(p-b)(p-c)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.24em;vertical-align:-0.305em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.935em;"><span class="svg-align" style="top:-3.2em;"><span class="pstrut" style="height:3.2em;"></span><span class="mord" style="padding-left:1em;"><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mclose">)</span></span></span><span style="top:-2.895em;"><span class="pstrut" style="height:3.2em;"></span><span class="hide-tail" style="min-width:1.02em;height:1.28em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.28em" viewbox="0 0 400000 1296" preserveaspectratio="xMinYMin slice"><path d="M263,681c0.7,0,18,39.7,52,119c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120c340,-704.7,510.7,-1060.3,512,-1067l0 -0c4.7,-7.3,11,-11,19,-11H40000v40H1012.3s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.305em;"><span></span></span></span></span></span></span></span></span></p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1231/learning/?page=1&amp;first_category_id=1&amp;problem_id=1231">1.三角形的面积 - 蓝桥云课</a></li></ul><p>注意在使用海伦公式的时候<strong>建议使用long double变量名，否则精度不够</strong>。</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_28">点击此处</a></p><h2 id="参考">参考</h2><ol><li><a href="https://leetcode.cn/circle/discuss/E3yavq/">力扣刷题攻略</a>  读者可以在这里参考刷题。</li><li>蓝桥云课C++班，作者谢子杨</li></ol>]]></content>
    
    
    <summary type="html">总结了C/C++赛道蓝桥杯常见的题型以及背后的算法原理,为读者提供一个刷题和总结的参考。</summary>
    
    
    
    <category term="algorithm" scheme="https://lloydkai.cn/categories/algorithm/"/>
    
    
    <category term="C" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>算法系列(三)蓝桥杯_算法高阶(二)</title>
    <link href="https://lloydkai.cn/posts/lanqiaocup-series-four/"/>
    <id>https://lloydkai.cn/posts/lanqiaocup-series-four/</id>
    <published>2025-02-16T07:16:45.000Z</published>
    <updated>2026-04-23T01:45:18.061Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/rVx9ogHB31wf4mJ.jpg" alt></p><h1>算法高阶</h1><blockquote><p>本部分算法难度较高，建议读者充分掌握算法基础之后再来学习。</p><p>目前以视频的方法为主，等蓝桥杯考完之后按照labuladong或者是考研的方法写代码。</p></blockquote><h2 id="我的仓库使用指南">我的仓库使用指南</h2><p>我的仓库链接格式如下：<code>https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/1_20</code> 其中1_20表示的是日期(一般是2025)，里面的文件就包含对应题目的解答(均通过对应题目的测试)或者是算法实现，其中文件名<code>lanqiao</code>表示 是<strong>蓝桥杯官网上的题目</strong>，<code>_</code> 后面的数字是蓝桥杯的<strong>题目编号</strong>，可以找到对应的蓝桥杯的题目，比如题目链接是<code>https://www.lanqiao.cn/problems/498/learning/?page=1&amp;first_category_id=1&amp;problem_id=498</code>    <code>problems</code>斜杠后面的数字<strong>498</strong> 就是对应的题目编号，你就在我指定链接下面的文件夹下按照<code>lanqiao_题目编号.cpp</code> 这样的格式找对应文件，就可以看到对应题目的解答代码。</p><p><img src="https://s2.loli.net/2025/02/06/n4dH1aOXoCc35Sy.png" alt="001_demo.png"></p><hr><h2 id="字符串">字符串</h2><h3 id="01trie">01trie</h3><p>【概念】：01字典树(01-tri)是一种特殊的字典树，它的字符集只有{0,1}，主要用来解决一些关于二进制上的问题，例如异或问题和子集问题</p><p>【例题引入】：给定n个数，求<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mi>i</mi></msub><mo>⨁</mo><msub><mi>a</mi><mi>j</mi></msub></mrow><annotation encoding="application/x-tex">a_i \bigoplus a_j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> 的最大值，其中<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>≤</mo><mn>2</mn><mo>×</mo><msup><mn>10</mn><mn>4</mn></msup><mo separator="true">,</mo><msub><mi>a</mi><mi>i</mi></msub><mo>≤</mo><msup><mn>10</mn><mn>9</mn></msup></mrow><annotation encoding="application/x-tex">n \leq 2 \times 10^4, a_i\leq 10^9</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span></span></span></span></span></span></span></span></p><p>将数组中所有正整数的二进制表示，按照从高位到低位的顺序，当作字符串挂载在tie树上，然后贪心的走，每一次走跟当前位相反的一位就可以了</p><h3 id="KMP和字符串Hash">KMP和字符串Hash</h3><p>【概念】：KMP算法是一种字符串匹配算法(在<strong>数据结构中有专门的篇章介绍此算法</strong>)，用于匹配模式串P在文本串S中出现的所有位置。例如S=“ababac’”，P=“aba”，那么出现的所有位置是13.在算法中，我们<strong>只需要记住和学会使用模板</strong>即可，对其原理只需简单理解，不要过度深究，避免把自己绕进去，可以课后自己慢慢去画图理解。KMP算法将原本O(n^2)的字符串匹配算法优化到了O(n),其精髓在于next数组，next数组表示此时<strong>模式串下标失配时应该移动到的位置</strong>，也表示<strong>最长的相同真前后缀的长度</strong>。</p><p>【实现】</p><p>示例模板如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e6</span><span class="number">+9</span>;</span><br><span class="line"><span class="type">char</span> s[N],p[N];</span><br><span class="line"><span class="type">int</span> nex[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line">  cin&gt;&gt;p;</span><br><span class="line">  <span class="type">int</span> m = <span class="built_in">strlen</span>(p<span class="number">+1</span>);</span><br><span class="line">  cin&gt;&gt;s;</span><br><span class="line">  <span class="type">int</span> n = <span class="built_in">strlen</span>(s<span class="number">+1</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">//获取next数组</span></span><br><span class="line">  nex[<span class="number">0</span>] = nex[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i  =<span class="number">2</span>,j=<span class="number">0</span>;i&lt;=m;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">while</span>(j&amp;&amp;p[i]!=p[j<span class="number">+1</span>])</span><br><span class="line">    &#123;</span><br><span class="line">      j=nex[j];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(p[i] == p[j<span class="number">+1</span>])</span><br><span class="line">    &#123;</span><br><span class="line">      j++;</span><br><span class="line">    &#125;</span><br><span class="line">    nex[i] = j;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="type">int</span> ans = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>,j=<span class="number">0</span>;i&lt;=n;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">while</span>(j &amp;&amp; s[i]!=p[j<span class="number">+1</span>])</span><br><span class="line">    &#123;</span><br><span class="line">      j = nex[j];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(s[i] == p[j<span class="number">+1</span>])</span><br><span class="line">    &#123;</span><br><span class="line">      j++;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(j == m)</span><br><span class="line">    &#123;</span><br><span class="line">      ans++;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  cout&lt;&lt;ans;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/2047/learning/?page=1&amp;first_category_id=1&amp;tag_relation=intersection&amp;problem_id=2047">1.斤斤计较的小Z - 蓝桥云课</a></li></ul><p>这一题基本上就是靠KMP算法的模板就能实现</p><h3 id="字符串Hash">字符串Hash</h3><p>【概念】：（基于进制的）字符串Hash本质上是用一个数字表示一段字符串(<strong>字符串与数字的映射关系</strong>)，从而降低字符串处理的复杂度。这个数字是一个很大的数字，采用unsigned longlong类型，可以自然溢出，从而简化了取模的部分。还需要一个进制数base,用于规定这个数字的进制。Hash数组h[i]表示字符串s[1~i]的Hash值，采用类似前缀和的形式以便于求出任意一个子串的Hash值。</p><p>【实现】</p><p>字符串Hash的初始化</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">unsigned</span> <span class="type">long</span> <span class="type">long</span> ull;</span><br><span class="line"><span class="type">const</span> ull base = <span class="number">131</span>;<span class="comment">//base一般为质数，减少hash冲突的概率</span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span> + <span class="number">9</span>;</span><br><span class="line">ull h[N];<span class="comment">//h[i]表示s[1-i]的hash前缀和</span></span><br><span class="line"><span class="type">char</span> s[N];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line">h[i] = h[i - <span class="number">1</span>] * base + s[i - <span class="string">&#x27;A&#x27;</span> + <span class="number">1</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>获取子串s[l]-s[r]的Hash(利用前缀和的性质)</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">ull <span class="title">getHash</span><span class="params">(<span class="type">int</span> l,<span class="type">int</span> r)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> h[r]-h[l<span class="number">-1</span>]*b[r-l<span class="number">+1</span>];<span class="comment">//b[i]表示base的i次方</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/2047/learning/?page=1&amp;first_category_id=1&amp;tag_relation=intersection&amp;problem_id=2047">1.斤斤计较的小Z - 蓝桥云课</a></li></ul><p>这里采用hash的方法求解，枚举所有匹配起点，然后利用hash直接判断查找即可。</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_16">点击此处</a></p><h3 id="回文串">回文串</h3><p>【概念】：回文串：类似ABA,ABCBA,AABBAA等的对于每个i具有sl=s[n+1-i]的字符串。回文半径：对于一个回文中心，如果它的半径为r,如果它为奇数长度的回文串的中心，则说明[i-r+1,i+r-1]为一个回文串。如果i是偶数长度的回文中心，则回文半径没有意义（Manacher算法会解决这个问题）</p><p>回文的递归性质：某个点的回文半径相比关于某个回文中心的点的回文半径一定相等或更大。举个例子，对于回文串ABACABAC,第二个B的回文半径至少是第一个B的回文半径。</p><p>【实现】：为了解决偶数长度回文半径没有意义的问题，Manacher发明了一种算法，他将<strong>所有的回文串都转化为了奇数长度的回文串</strong>。方法就是在字符串中间和头尾插入特殊字符，例如原字符串为ABBA,转换后变为^#A#B#B#A#$,于是我们就可以得到^#A#B#B#A#$中两个B之间的<code>#</code>的回文半径为5，它就表示在原字符串中的回文半径为5-1=4（这个原因待会儿会解释）。<br>Manacher算法是一种O(n)复杂度计算<strong>字符串中每个位置作为回文中心的回文半径</strong>的算法。位置的回文半径以p[i]表示，意思是在转换后的字符串中[i-p[i]+1,i+p[i]-1]是回文的。</p><p>转换后的字符串中回文半径为p[i]（必然为偶数），说明在转换前的回文串中回文半径为p[i]-1,转换前的回文串长度为p[i]-1。推导公式为</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mfrac><mrow><msub><mi>p</mi><mi>i</mi></msub><mo>+</mo><msub><mi>p</mi><mi>i</mi></msub><mo>−</mo><mn>1</mn></mrow><mn>2</mn></mfrac><mo stretchy="false">]</mo><mo>=</mo><mo stretchy="false">[</mo><msub><mi>p</mi><mi>i</mi></msub><mo>−</mo><mfrac><mn>1</mn><mn>2</mn></mfrac><mo stretchy="false">]</mo><mo>=</mo><msub><mi>p</mi><mi>i</mi></msub><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">[\frac{p_i+p_i-1}{2}]=[p_i-\frac{1}{2}]=p_i-1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2422em;vertical-align:-0.345em;"></span><span class="mopen">[</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8972em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">+</span><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p>转换后的字符串的有效区间为为[1,2 * n+1],所以我们从1到2*n+1去遍历所有点。如果i&lt;R说明i存在关于C(C是此时最右侧的R所对应的对称中心)的对称点2C-i,那么p就可以等于p[2C-i],当然为了防止越界，要和R-i取小。如果i&gt;=R说明已经无法通过C找到对称点了，因为此时i不在C的回文区间中，就不存在回文的递归性质。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1225/learning/?page=1&amp;first_category_id=1&amp;problem_id=1225">1.最长回文子串 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_17">点击此处</a></p><h3 id="字典树">字典树</h3><p>【例子引入】：给n个字符串s1-sn,再给1个字符串t,如何快速查找t是否在s出现过？朴素的方法是循环遍历s1~sn,并比较si是否和t相等即可。这样做对于每一次询问的时间复杂度为O（）,如果t的数量较多（即询问次数较多），则会超时。当然前面介绍过KMP算法可以解决此问题，不过我们接下来要介绍的是用字典树的方式解决问题。</p><p>【概念】：字典树也叫Trie树，是一种树形结构，其中每个结点上可以存储（当然也可以不存储）一些变量用于表示该字符串的数量（右图中结点上的数字表示结点编号），每条边表示一个字符。假如结点9里面存储一个变量cnt=3,说明存在3个字符串为“cbc”每个结点仅存在一条到根节点的路径，这条路径上的所有边就表示一条字符串。</p><p>【实现】</p><ol><li>建立字典树</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> nex[N][<span class="number">27</span>];<span class="comment">//nex[i][0]表示从节点出发，边为a的下一个节点地址</span></span><br><span class="line"><span class="type">int</span> cnt[N] ;<span class="comment">//cnt[i]表示以节点i结尾的字符串数量</span></span><br><span class="line"><span class="type">int</span> idx = <span class="number">2</span>;<span class="comment">//内存池，用语动态开点</span></span><br><span class="line"><span class="comment">//初始时，只有一个节点1作为根节点 </span></span><br></pre></td></tr></table></figure><ol start="2"><li>编写一个insert函数，用于将一个字符串s加入到字典树中</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">insert</span><span class="params">(<span class="type">char</span> s[])</span> <span class="comment">//长度为n的字符串s插入到trie中 </span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n = <span class="built_in">strlen</span>(s<span class="number">+1</span>);</span><br><span class="line"><span class="type">int</span> x = <span class="number">1</span>;<span class="comment">//从1开始往下面走</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//先检查x是否存在s[i]的边</span></span><br><span class="line"><span class="keyword">if</span>(!nex[x][s[i]-<span class="string">&#x27;a&#x27;</span>]]) </span><br><span class="line">&#123;</span><br><span class="line">nex[x][s[i]-<span class="string">&#x27;a&#x27;</span>]] = idx++;</span><br><span class="line">&#125;</span><br><span class="line">x = nex[s][s[i]-<span class="string">&#x27;a&#x27;</span>]];<span class="comment">//x移动到新点上 </span></span><br><span class="line">&#125;</span><br><span class="line">cnt[x]++;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol start="3"><li>编写一个check函数，用于判断某个字符在trie中的出现次数</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">check</span><span class="params">(<span class="type">char</span> s[])</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n = <span class="built_in">strlen</span>(s<span class="number">+1</span>);</span><br><span class="line"><span class="type">int</span> x = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">x = nex[x][s[i]-<span class="string">&#x27;a&#x27;</span>];</span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">return</span> cnt[x];</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1204/learning/?page=1&amp;first_category_id=1&amp;problem_id=1204">1.前缀判定 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_17">点击此处</a></p><h2 id="数学与算法">数学与算法</h2><h3 id="费马小定理">费马小定理</h3><blockquote><p>注意这里的重点不在于费马小定理，而是后面的<strong>逆元思想</strong></p></blockquote><p>【概念】：若p为质数，且gcd(a,p)=1(翻译以下就是<strong>两数的最大公约数为1，即两数互质</strong>),则有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mrow><mi>p</mi><mo>−</mo><mn>1</mn></mrow></msup><mo>=</mo><mn>1</mn><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>p</mi><mo stretchy="false">)</mo></mspace></mspace></mrow><annotation encoding="application/x-tex">a^{p-1} = 1 \pmod p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span>.</p><p>因为p是一个质数，所以对于任意&lt;p的正整数a,都有gcd(a,p)=1 。般来讲题目给的模数都是一个质数，从而满足费马小定理，可以使用费马小定理来求逆元。</p><p>【概念】：<strong>逆元</strong>：如果<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>×</mo><mi>c</mi><mo>=</mo><mn>1</mn><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>p</mi><mo stretchy="false">)</mo></mspace></mspace></mrow><annotation encoding="application/x-tex">a \times c= 1 \pmod p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span>,则乘c为a的逆元，也记作<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup></mrow><annotation encoding="application/x-tex">a^{-1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span>,<strong>逆元是一个整数</strong>。对费马小定理的式子两边同时除以一个a,得到<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mrow><mi>p</mi><mo>−</mo><mn>2</mn></mrow></msup><mo>=</mo><msup><mi>a</mi><mrow><mi>p</mi><mo>−</mo><mn>1</mn></mrow></msup><mo>×</mo><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><mi>c</mi><mo>=</mo><mn>1</mn><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>p</mi><mo stretchy="false">)</mo><mo>×</mo><msup><mi>a</mi><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo separator="true">;</mo><msup><mi>a</mi><mrow><mi>p</mi><mo>−</mo><mn>1</mn></mrow></msup><mo>=</mo><mn>1</mn><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>p</mi><mo stretchy="false">)</mo><mo separator="true">;</mo><mo>=</mo><mo>&gt;</mo><msup><mi>a</mi><mrow><mi>p</mi><mo>−</mo><mn>2</mn></mrow></msup><mo>=</mo><mfrac><mn>1</mn><mi>a</mi></mfrac></mspace></mspace></mspace></mspace></mrow><annotation encoding="application/x-tex">a^{p-2} =a^{p-1}\times a^{-1};c=1 \pmod p \times a^{-1};a^{p-1}=1 \pmod p; =&gt;a^{p-2}= \frac{1}{a}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mtight">2</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mtight">2</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>.于是我们就得到了a的逆元，即1/a的在mod p意义下的整数形式，就是a的p-2次方。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">ll <span class="title">inv</span><span class="params">(ll x)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">qmi</span>(x,p<span class="number">-2</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1157/learning/?page=1&amp;first_category_id=1&amp;problem_id=1157">1.乘法逆元 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/3932/learning/?page=1&amp;first_category_id=1&amp;problem_id=3932">1.获胜的概率 - 蓝桥云课</a></li></ul><p>首先特判k=0时，1号获胜。然后k为奇数时，所有偶数号的选手平摊获胜概率。k为偶数时，所有奇数号选手平摊获胜概率。然后计算n有多少个偶数和奇数就可以了。当然这里要用到逆元的思想</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_17">点击此处</a></p><h3 id="高斯消元法">高斯消元法</h3><p>【概念】高斯消元法是一个用来求解线性程组的算法，在线性代数里面有专门的计算部分，而这里的高斯消元法就是用计算机去模拟人使用高斯消元法的步骤。</p><blockquote><p>PS:因为我学过数值计算(研究生课程)，里面就专门介绍如何用Python实现高斯消元法，是通过多次迭代+取值实现的</p></blockquote><p>高斯消元的目的是，先进行加减消元，然后我们可以先求得一个未知数的值，然后可以逐层往回代，也就是代入消元法，依次可以得到定第2个、第3个未知数的值，以至第个未知数。最终解出方程组中各个未知数。</p><p>演示如下</p><p>给定一个线性方程组：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mn>2</mn><mi>x</mi><mo>+</mo><mn>4</mn><mi>y</mi><mo>−</mo><mn>2</mn><mi>z</mi><mo>=</mo><mn>2</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mn>4</mn><mi>x</mi><mo>+</mo><mn>9</mn><mi>y</mi><mo>−</mo><mn>3</mn><mi>z</mi><mo>=</mo><mn>8</mn></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>2</mn><mi>x</mi><mo>−</mo><mn>3</mn><mi>y</mi><mo>+</mo><mn>7</mn><mi>z</mi><mo>=</mo><mn>10</mn></mrow></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">\begin{cases}2x + 4y - 2z = 2 \\4x + 9y - 3z = 8 \\-2x - 3y + 7z = 10\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewbox="0 0 888.89 316" preserveaspectratio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewbox="0 0 888.89 316" preserveaspectratio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">2</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">2</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">4</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">9</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">3</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">8</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">−</span><span class="mord">2</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">3</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">7</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">10</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></p><p>我们可以将其表示为增广矩阵的形式：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.16em" columnalign="center center center center center" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>2</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>2</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>2</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>9</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>3</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>8</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>2</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>3</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>7</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>10</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}2 &amp; 4 &amp; -2 &amp; | &amp; 2 \\4 &amp; 9 &amp; -3 &amp; | &amp; 8 \\-2 &amp; -3 &amp; 7 &amp; | &amp; 10\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewbox="0 0 667 3600"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">9</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">3</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">7</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">8</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">10</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewbox="0 0 667 3600"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span></span></span></span><br>一般消元的步骤如下：</p><ol><li>将第一列的下三角部分变为零。</li></ol><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.16em" columnalign="center center center center center" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>2</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>2</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>2</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>5</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>12</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}2 &amp; 4 &amp; -2 &amp; | &amp; 2 \\0 &amp; 1 &amp; 1 &amp; | &amp; 4 \\0 &amp; 1 &amp; 5 &amp; | &amp; 12\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewbox="0 0 667 3600"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">5</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">12</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewbox="0 0 667 3600"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span></span></span></span></p><ol start="2"><li>将第二列的下三角部分变为零。</li></ol><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.16em" columnalign="center center center center center" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>2</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>2</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>2</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>4</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi mathvariant="normal">∣</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>8</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}2 &amp; 4 &amp; -2 &amp; | &amp; 2 \\0 &amp; 1 &amp; 1 &amp; | &amp; 4 \\0 &amp; 0 &amp; 4 &amp; | &amp; 8\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewbox="0 0 667 3600"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">∣</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">8</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewbox="0 0 667 3600"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span></span></span></span></p><ol start="3"><li>通过回代求解未知数。</li></ol><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>4</mn><mi>z</mi><mo>=</mo><mn>8</mn><mo>⇒</mo><mi>z</mi><mo>=</mo><mn>2</mn><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">4z = 8 \Rightarrow z = 2;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">8</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">;</span></span></span></span> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mo>+</mo><mn>2</mn><mo>=</mo><mn>4</mn><mo>⇒</mo><mi>y</mi><mo>=</mo><mn>2</mn><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">y + 2 = 4 \Rightarrow y = 2;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">4</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">;</span></span></span></span> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>x</mi><mo>+</mo><mn>4</mn><mo>×</mo><mn>2</mn><mo>−</mo><mn>2</mn><mo>×</mo><mn>2</mn><mo>=</mo><mn>2</mn><mo>⇒</mo><mn>2</mn><mi>x</mi><mo>+</mo><mn>8</mn><mo>−</mo><mn>4</mn><mo>=</mo><mn>2</mn><mo>⇒</mo><mn>2</mn><mi>x</mi><mo>=</mo><mo>−</mo><mn>2</mn><mo>⇒</mo><mi>x</mi><mo>=</mo><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">2x + 4 \times 2 - 2 \times 2 = 2 \Rightarrow 2x + 8 - 4 = 2 \Rightarrow 2x = -2 \Rightarrow x = -1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">4</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">8</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">4</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">1</span></span></span></span></p><blockquote><p>高斯消元法通过逐步消元，将线性方程组转化为<strong>上三角矩阵</strong>，然后通过回代求解未知数。这种方法适用于<strong>任何可逆的线性方程组</strong>。</p></blockquote><p>如果用暴力枚举来消元，示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">510</span>;</span><br><span class="line"><span class="type">int</span> n;<span class="comment">//n个方程就有n个未知数</span></span><br><span class="line"><span class="type">double</span> a[MAXN][MAXN];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;n);</span><br><span class="line"><span class="comment">//初始化参数到对应的数组中 </span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n + <span class="number">1</span>; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%1f&quot;</span>, &amp;a[i][j]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//开始消元 </span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> maxx = i;<span class="comment">//max比大小</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = i + <span class="number">1</span>; j &lt;= n; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">fabs</span>(a[j][i]) &gt; <span class="built_in">fabs</span>(a[maxx][i]))</span><br><span class="line">&#123;</span><br><span class="line">maxx = j;<span class="comment">//记录最大值的下标</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n + <span class="number">1</span>; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">swap</span>(a[i][j], a[maxx][j]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//第i行第i列a[i][i]</span></span><br><span class="line"><span class="keyword">if</span> (!a[i][i] == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">double</span> k = a[i][i];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (j != i)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> k = i + <span class="number">1</span>; k &lt;= n + <span class="number">1</span>; k++)</span><br><span class="line">&#123;</span><br><span class="line">a[j][k] -= a[i][k] * a[j][i] / k;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%.2lf\n&quot;</span>, a[i][n + <span class="number">1</span>] / a[i][i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>而使用高斯消元法的算法实现如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">510</span>;</span><br><span class="line"><span class="type">int</span> n;<span class="comment">//n个方程就有n个未知数</span></span><br><span class="line"><span class="type">double</span> a[MAXN][MAXN], ans[MAXN];</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义一个解决函数</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">solve</span><span class="params">(<span class="type">int</span> n, <span class="type">int</span> m)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> r = i;<span class="comment">//记录最大值的下标 </span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = i + <span class="number">1</span>; j &lt;= n; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">fabs</span>(a[r][i]) &lt; <span class="built_in">fabs</span>(a[j][i]))</span><br><span class="line">&#123;</span><br><span class="line">r = j;<span class="comment">//记录最大值的下标</span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//第i行第i列a[i][i]</span></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">fabs</span>(a[r][i]))</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n + <span class="number">1</span>; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">swap</span>(a[i][j], a[r][j]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">double</span> div = a[i][i];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n + <span class="number">1</span>; j++)</span><br><span class="line">&#123;</span><br><span class="line">a[i][j] /= a[i][i];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = i + <span class="number">1</span>; j &lt;= n; j++)</span><br><span class="line">&#123;</span><br><span class="line">div = a[j][i];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> k = i; k &lt;= n + <span class="number">1</span>; k++)</span><br><span class="line">&#123;</span><br><span class="line">a[j][k] -= a[i][k] * div;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">ans[n] = a[n][n + <span class="number">1</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = n - <span class="number">1</span>; i &gt;= <span class="number">1</span>; i--)</span><br><span class="line">&#123;</span><br><span class="line">ans[i] = a[i][n + <span class="number">1</span>];</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = i + <span class="number">1</span>; j &lt;= n; j++)</span><br><span class="line">&#123;</span><br><span class="line">ans[i] -= (a[i][j] * ans[j]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%.2lf\n&quot;</span>, ans[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>, &amp;n);</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= n + <span class="number">1</span>; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%lf&quot;</span>, &amp;a[i][j]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> guass = <span class="built_in">solve</span>(n, n);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li>高斯消元完成后，若存在系数全为0、常数不为0的行，则方程组无解。</li><li>若系数不全为0的行恰好有n个，则主元有n个，方程组有唯一解。</li><li>系数不为0的行&lt;n个，则有无数个解。</li></ol><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/827/learning/?page=1&amp;first_category_id=1&amp;name=%E7%90%83%E5%BD%A2%E7%A9%BA%E9%97%B4">1.球形空间产生器 - 蓝桥云课</a></li></ul><p>一个球体上的所有点到球心距离相等，因此我们只需求出一个点(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mn>1</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>2</mn></msub><mo separator="true">,</mo><msub><mi>x</mi><mn>3</mn></msub><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><msub><mi>x</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">x_1,x_2,x_3....x_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">....</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>),使得：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>0</mn></mrow><mi>n</mi></msubsup><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub><mo>−</mo><msub><mi>x</mi><mi>j</mi></msub><msup><mo stretchy="false">)</mo><mn>2</mn></msup><mo>=</mo><mi>C</mi></mrow><annotation encoding="application/x-tex">\sum_{j=0}^{n}(a_{i,j}-x_j)^2=C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2401em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1002em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span>其中C为常数，a,是点的坐标，解方程组由n+1个n元二次方程构成，当然不是线性的，怎么办呢？？我们可以通过相邻两个方程做差，变成个n元一次方程组，消去常数C。有点像数学中数列求通项公式或者前项和。即</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo stretchy="false">(</mo><msubsup><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow><mn>2</mn></msubsup><mo>−</mo><msubsup><mi>a</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi></mrow><mn>2</mn></msubsup><mo>−</mo><mn>2</mn><msub><mi>x</mi><mi>j</mi></msub><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub><mo>−</mo><msub><mi>a</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi></mrow></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\sum_{j=1}^{n}(a_{i,j}^{2}-a_{i+1,j}^{2}-2x_j(a_{i,j}-a_{i+1,j}))=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2499em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4413em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3948em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2089em;vertical-align:-0.3948em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4413em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3948em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span><br>把变量放左边，常数放右边：</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><msub><mi>x</mi><mi>j</mi></msub><mo stretchy="false">(</mo><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub><mo>−</mo><msub><mi>a</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi></mrow></msub><mo stretchy="false">)</mo><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo stretchy="false">(</mo><msubsup><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow><mn>2</mn></msubsup><mo>−</mo><msubsup><mi>a</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi></mrow><mn>2</mn></msubsup><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mi>i</mi><mo>=</mo><mn>1</mn><mo separator="true">,</mo><mn>2</mn><mo separator="true">,</mo><mn>3...</mn><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">2x_j(a_{i,j}-a_{i+1,j})=\sum_{j=1}^{n}(a_{i,j}^{2}-a_{i+1,j}^{2})(i=1,2,3...n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2499em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4413em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3948em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2089em;vertical-align:-0.3948em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4413em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3948em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">3...</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></p><p>套用前面的模板，加上一个二维的数组就基本可以解决</p><ul><li><a href="https://www.lanqiao.cn/problems/1469/learning/?page=1&amp;first_category_id=1&amp;name=%E5%A7%8B%E7%A5%96%E9%B8%9F">1.始祖鸟 - 蓝桥云课</a></li></ul><p>有两种情况，如果一只鸟有偶数个朋友，那么只需要保证有偶数个,朋友在上游，就会有偶数个朋友在下游，这只鸟去哪里都可以。如果这只鸟有奇数个朋友，那么就要保证这只鸟去有偶数个朋友的区域。用xi=0表示去下游，xi=1表示去上游</p><p>对于有偶数个朋友的鸟：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mrow><mi>a</mi><mn>1</mn></mrow></msub><mo>⨁</mo><msub><mi>x</mi><mrow><mi>a</mi><mn>2</mn></mrow></msub><mo>⨁</mo><msub><mi>x</mi><mrow><mi>a</mi><mn>3</mn></mrow></msub><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>⨁</mo><msub><mi>x</mi><mrow><mi>a</mi><mi>m</mi></mrow></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">x_{a1} \bigoplus x_{a2} \bigoplus x_{a3}....\bigoplus x_{am}=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mtight">3</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">....</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">am</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></p><p>对于有奇数个朋友的鸟：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>x</mi><mrow><mi>a</mi><mn>1</mn></mrow></msub><mo>⨁</mo><msub><mi>x</mi><mrow><mi>a</mi><mn>2</mn></mrow></msub><mo>⨁</mo><msub><mi>x</mi><mrow><mi>a</mi><mn>3</mn></mrow></msub><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>⨁</mo><msub><mi>x</mi><mrow><mi>a</mi><mi>m</mi></mrow></msub><mo>⨁</mo><msub><mi>x</mi><mi>i</mi></msub><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">x_{a1} \bigoplus x_{a2} \bigoplus x_{a3}....\bigoplus x_{am} \bigoplus x_{i}=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mtight">3</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">....</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">am</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">⨁</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_17">点击此处</a></p><h3 id="矩阵乘法、整除、同余、LCM和GCD">矩阵乘法、整除、同余、LCM和GCD</h3><h4 id="矩阵乘法">矩阵乘法</h4><p>【概念】：矩阵的乘法在线性代数中有详细的介绍，不懂的去看宋浩的课(❁´◡`❁)。这里补充几点。</p><ol><li>每个矩阵有一个行数和一个列数，只有当相乘的两个矩阵的左矩阵的列数等于右矩阵的行数时，才能相乘，否则不允许做矩阵乘法。</li><li>矩阵乘法的规则用计算机语言描述就是，第一个矩阵A的第i行和第二个矩阵B的第j列的各M个元素对应相乘再相加得到新矩阵<code>C[i][j]</code>的值。</li></ol><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1550/learning/?page=1&amp;first_category_id=1&amp;problem_id=1550">1.矩阵相乘 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_18">点击此处</a></p><h4 id="整除">整除</h4><p>【概念】：在计算机中，整数之间的除法往往是整除且向下取整的，例如：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mfrac><mn>12</mn><mn>5</mn></mfrac><mo stretchy="false">]</mo><mo>=</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">[\frac{12}{5}]=2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mopen">[</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">5</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span></span></span></span> C++就是默认向下去整。</p><p>如果要向上去整呢？如果要计算x/y向上取整，需要改写式子为(x+y-1)/y或(x-1)/y+1。其中如果x可以被y整除，记作<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>y</mi><mi mathvariant="normal">∣</mi><mi>x</mi></mrow><annotation encoding="application/x-tex">y|x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">∣</span><span class="mord mathnormal">x</span></span></span></span> 比如4|12;</p><p>整除的性质如下</p><ul><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>⟺</mo><mo>−</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>⟺</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mo>−</mo><mi>b</mi><mo>⟺</mo><mi mathvariant="normal">∣</mi><mi>a</mi><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mi mathvariant="normal">∣</mi></mrow><annotation encoding="application/x-tex">a|b \Longleftrightarrow -a|b \Longleftrightarrow a|-b \Longleftrightarrow |a|||b|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7184em;vertical-align:-0.024em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mord">∣∣∣</span><span class="mord mathnormal">b</span><span class="mord">∣</span></span></span></span></li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>∧</mo><mi>b</mi><mi mathvariant="normal">∣</mi><mi>c</mi><mo>⟹</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mi>c</mi></mrow><annotation encoding="application/x-tex">a|b \land b|c \Longrightarrow a|c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">c</span></span></span></span>  这里的<code>^</code>是<strong>逻辑与</strong> 在<strong>离散数学中是且的意思</strong></li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>∧</mo><mi>b</mi><mi mathvariant="normal">∣</mi><mi>c</mi><mo>⟺</mo><mi mathvariant="normal">∀</mi><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo>∈</mo><mi>Z</mi><mo separator="true">,</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mo stretchy="false">(</mo><mi>x</mi><mi>b</mi><mo>+</mo><mi>y</mi><mi>c</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a|b \land b|c \Longleftrightarrow \forall x,y \in Z,a|(xb+yc)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">yc</span><span class="mclose">)</span></span></span></span> 这里的xb+yc是b、c的线性组合</li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>∧</mo><mi>b</mi><mi mathvariant="normal">∣</mi><mi>a</mi><mo>⟹</mo><mi>b</mi><mo>=</mo><mo>±</mo><mi>a</mi></mrow><annotation encoding="application/x-tex">a|b \land b|a \Longrightarrow b=\pm a</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">±</span><span class="mord mathnormal">a</span></span></span></span></li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>f</mi><mspace width="1em"><mi>m</mi><mo mathvariant="normal">≠</mo><mn>0</mn><mo separator="true">,</mo><mi>t</mi><mi>h</mi><mi>e</mi><mi>n</mi><mspace width="1em"><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>⟺</mo><mi>m</mi><mi>a</mi><mi mathvariant="normal">∣</mi><mi>m</mi><mi>b</mi></mspace></mspace></mrow><annotation encoding="application/x-tex">if \quad m \neq0,then \quad a|b \Longleftrightarrow ma|mb</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:1em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:1em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord">∣</span><span class="mord mathnormal">mb</span></span></span></span></li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>f</mi><mspace width="1em"><mi>b</mi><mo mathvariant="normal">≠</mo><mn>0</mn><mo separator="true">,</mo><mi>t</mi><mi>h</mi><mi>e</mi><mi>n</mi><mspace width="1em"><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>⟹</mo><mi mathvariant="normal">∣</mi><mi>a</mi><mi mathvariant="normal">∣</mi><mo>≤</mo><mi mathvariant="normal">∣</mi><mi>b</mi><mi mathvariant="normal">∣</mi></mspace></mspace></mrow><annotation encoding="application/x-tex">if \quad b \neq0,then \quad a|b \Longrightarrow |a|\leq |b|</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:1em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:1em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mord">∣</span></span></span></span></li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mi>f</mi><mspace width="1em"><mi>a</mi><mo mathvariant="normal">≠</mo><mn>0</mn><mo separator="true">,</mo><mi>b</mi><mo>=</mo><mi>q</mi><mi>a</mi><mo>+</mo><mi>c</mi><mo separator="true">,</mo><mi>t</mi><mi>h</mi><mi>e</mi><mi>n</mi><mspace width="1em"><mi>a</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo>⟺</mo><mi>a</mi><mi mathvariant="normal">∣</mi><mi>c</mi></mspace></mspace></mrow><annotation encoding="application/x-tex">if \quad a \neq0,b=qa+c,then \quad a|b \Longleftrightarrow a|c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:1em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:1em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">c</span></span></span></span></li></ul><h4 id="同余">同余</h4><p>【概念】：意思是<strong>两个或多个数字x,对于一个模数M的余数是相等的</strong>，或者说在模M意义下，他们是相等的。例如当M=7,x=[1,8,15,8,50]是同余的，这些x有一个共同的关系，就是x%M=1。</p><p>同余的性质：</p><ul><li>自反性：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>a</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv a (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>。</li><li>对称性：若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi><mo>≡</mo><mi>a</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">b \equiv a (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>。</li><li>传递性：若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>b</mi><mo>≡</mo><mi>c</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">b \equiv c (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>c</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv c (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>。</li><li>线性运算：<ul><li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo separator="true">,</mo><mi>c</mi><mo separator="true">,</mo><mi>d</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">a, b, c, d \in \mathbb{Z}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">Z</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mo>∈</mo><msup><mi mathvariant="double-struck">N</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">m \in \mathbb{N}^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>c</mi><mo>≡</mo><mi>d</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">c \equiv d (\text{mod } n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>，则有：<ul><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>±</mo><mi>c</mi><mo>≡</mo><mi>b</mi><mo>±</mo><mi>d</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \pm c \equiv b \pm d (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">±</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">±</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>。</li><li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>×</mo><mi>c</mi><mo>≡</mo><mi>b</mi><mo>×</mo><mi>d</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \times c \equiv b \times d (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>。</li></ul></li><li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">a, b \in \mathbb{Z}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">Z</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mo separator="true">,</mo><mi>m</mi><mo>∈</mo><msup><mi mathvariant="double-struck">N</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">k, m \in \mathbb{N}^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>k</mi><mo>≡</mo><mi>b</mi><mi>k</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a k \equiv b k (\text{mod } mk)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">ak</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">bk</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal" style="margin-right:0.03148em;">mk</span><span class="mclose">)</span></span></span></span>。</li><li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">a, b \in \mathbb{Z}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">Z</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo separator="true">,</mo><mi>m</mi><mo>∈</mo><msup><mi mathvariant="double-struck">N</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">d, m \in \mathbb{N}^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi mathvariant="normal">∣</mi><mi>a</mi><mo separator="true">,</mo><mi>d</mi><mi mathvariant="normal">∣</mi><mi>b</mi><mo separator="true">,</mo><mi>d</mi><mi mathvariant="normal">∣</mi><mi>m</mi></mrow><annotation encoding="application/x-tex">d | a, d | b, d | m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord">∣</span><span class="mord mathnormal">m</span></span></span></span>，则当<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>成立时，有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mi>a</mi><mi>d</mi></mfrac><mo>≡</mo><mfrac><mi>b</mi><mi>d</mi></mfrac><mo stretchy="false">(</mo><mtext>mod </mtext><mfrac><mi>m</mi><mi>d</mi></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\frac{a}{d} \equiv \frac{b}{d} (\text{mod } \frac{m}{d})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0404em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6954em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2251em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6954em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span></span></span></span>。</li><li>若<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo separator="true">,</mo><mi>b</mi><mo>∈</mo><mi mathvariant="double-struck">Z</mi></mrow><annotation encoding="application/x-tex">a, b \in \mathbb{Z}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">Z</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo separator="true">,</mo><mi>m</mi><mo>∈</mo><msup><mi mathvariant="double-struck">N</mi><mo>∗</mo></msup></mrow><annotation encoding="application/x-tex">d, m \in \mathbb{N}^*</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi mathvariant="normal">∣</mi><mi>m</mi></mrow><annotation encoding="application/x-tex">d | m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord">∣</span><span class="mord mathnormal">m</span></span></span></span>，则当<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>m</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } m)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>成立时，有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mo>≡</mo><mi>b</mi><mo stretchy="false">(</mo><mtext>mod </mtext><mi>d</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a \equiv b (\text{mod } d)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4637em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mopen">(</span><span class="mord text"><span class="mord">mod </span></span><span class="mord mathnormal">d</span><span class="mclose">)</span></span></span></span>。</li></ul></li></ul><h4 id="GCD和LCM">GCD和LCM</h4><p>【概念】：GCD(Greatest Common Divisor)是最大公约数，LCM(Least Common Multiple)是最小公倍数。大多数情况下，我们更关注GCD,如果题目和LCM有关，也通常会转换成和GCD相关的(<strong>前面费马小定理介绍过</strong>)<br>gC通过欧几里得辗转相除法得到，同样，初次学习不必过于深究其原理，学会使用最重要。lcm通过gcd(x，y) * lcm(x,y)=x * y来得到。C++中已经有了对应的函数</p><p>这里简单介绍一下实现方法</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//辗转相除法</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">gcd</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> b == <span class="number">0</span>?a:<span class="built_in">gcd</span>(b,a%b);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>简单地理解一下，首先不妨设a&lt;b,有gcd(a,b)=gcd(a,b-a=gcd(a,b-2a=gcd(a,b%a),b%a&lt;a,于是将他们两个调换位置，继续向下递归，直到b变为0,gcd(x，0)=x。</p><p>LCM的实现方法</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">lcm</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">return</span> a/<span class="built_in">gcd</span>(a,b)*b;<span class="comment">//这里推荐先除后乘，避免溢出</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1260/learning/?page=1&amp;first_category_id=1&amp;problem_id=1260">1.最大公约数 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_18">点击此处</a></p><h3 id="快速幂原理">快速幂原理</h3><p>【概念】：朴素的计算a的b次方的方法，所需的时间复杂度为O(b),即用一个循环，每次乘一个a,乘b次。利用倍增的思想，可以将求幂运算的时间复杂度降低为O(logb).当b为偶数：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mi>b</mi></msup><mo>=</mo><msup><mi>a</mi><mfrac><mi>b</mi><mn>2</mn></mfrac></msup><mo>×</mo><msup><mi>a</mi><mfrac><mi>b</mi><mn>2</mn></mfrac></msup><mo>=</mo><mo stretchy="false">(</mo><msup><mi>a</mi><mn>2</mn></msup><msup><mo stretchy="false">)</mo><mfrac><mi>b</mi><mn>2</mn></mfrac></msup></mrow><annotation encoding="application/x-tex">a^b=a^{\frac{b}{2}} \times a^{\frac{b}{2}}= (a^2)^{\frac{b}{2}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0623em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.979em;"><span style="top:-3.363em;margin-right:0.05em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.88em;"><span style="top:-2.656em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.2255em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line mtight" style="border-bottom-width:0.049em;"></span></span><span style="top:-3.384em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.344em;"><span></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.979em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.979em;"><span style="top:-3.363em;margin-right:0.05em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.88em;"><span style="top:-2.656em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.2255em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line mtight" style="border-bottom-width:0.049em;"></span></span><span style="top:-3.384em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.344em;"><span></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.229em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.979em;"><span style="top:-3.363em;margin-right:0.05em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.88em;"><span style="top:-2.656em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.2255em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line mtight" style="border-bottom-width:0.049em;"></span></span><span style="top:-3.384em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.344em;"><span></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span></span></span></span></span></span></span></span></span></span></span></span> 当b为奇数：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mi>b</mi></msup><mo>=</mo><mi>a</mi><mo>×</mo><msup><mi>a</mi><mfrac><mi>b</mi><mn>2</mn></mfrac></msup><mo>×</mo><msup><mi>a</mi><mfrac><mi>b</mi><mn>2</mn></mfrac></msup><mo>=</mo><mi>a</mi><mo>×</mo><mo stretchy="false">(</mo><msup><mi>a</mi><mn>2</mn></msup><msup><mo stretchy="false">)</mo><mfrac><mi>b</mi><mn>2</mn></mfrac></msup></mrow><annotation encoding="application/x-tex">a^b=a\times a^{\frac{b}{2}} \times a^{\frac{b}{2}}= a\times(a^2)^{\frac{b}{2}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0623em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.979em;"><span style="top:-3.363em;margin-right:0.05em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.88em;"><span style="top:-2.656em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.2255em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line mtight" style="border-bottom-width:0.049em;"></span></span><span style="top:-3.384em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.344em;"><span></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.979em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.979em;"><span style="top:-3.363em;margin-right:0.05em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.88em;"><span style="top:-2.656em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.2255em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line mtight" style="border-bottom-width:0.049em;"></span></span><span style="top:-3.384em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.344em;"><span></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.229em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.979em;"><span style="top:-3.363em;margin-right:0.05em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mopen nulldelimiter sizing reset-size3 size6"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.88em;"><span style="top:-2.656em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.2255em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line mtight" style="border-bottom-width:0.049em;"></span></span><span style="top:-3.384em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.344em;"><span></span></span></span></span></span><span class="mclose nulldelimiter sizing reset-size3 size6"></span></span></span></span></span></span></span></span></span></span></span></span></span>,注意这里b/2向下取整。于是迭代求解，直到b为0即可。</p><blockquote><p>求幂本质是求乘法，但是在乘法器中求乘法时间会很长，学过微机原理的同学应该有所体会，所以需要对求幂进行优化</p></blockquote><p>【实现】：实现方法如下，以后记住，<strong>qmi就是快速幂函数</strong>，<strong>一旦题目中讲到幂的运算或者是取模，就要优先考虑是否使用快速幂</strong>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">qmi</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> b,<span class="type">int</span> p)</span><span class="comment">//对p求模 根据题目数据的规模选择int 或者long long</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">int</span> res = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(b)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span>(b&amp;<span class="number">1</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            res = res*a%p;<span class="comment">//b为奇数时，乘以一个a到答案里面</span></span><br><span class="line">        &#125;</span><br><span class="line">        a=a*a;</span><br><span class="line">        b&gt;&gt;=<span class="number">1</span>;<span class="comment">//底数平方，指数除以2</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1181/learning/?page=1&amp;first_category_id=1&amp;problem_id=1181">1.数的幂次 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_18">点击此处</a></p><h3 id="欧拉函数与欧拉降幂">欧拉函数与欧拉降幂</h3><p>【概念】:欧拉函数phi(n)表示&lt;=n的且与n互质的数的个数，按照定义有phi(1)=1。<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>ϕ</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>p</mi><mn>1</mn></msub></mfrac><mo stretchy="false">)</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>p</mi><mn>2</mn></msub></mfrac><mo stretchy="false">)</mo><mo>…</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><msub><mi>p</mi><mi>m</mi></msub></mfrac><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\phi(n)=n(1-\frac1{p_1})(1-\frac1{p_2})\ldots(1-\frac1{p_m})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.3262em;vertical-align:-0.4811em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4811em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.3262em;vertical-align:-0.4811em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4811em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.3262em;vertical-align:-0.4811em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4811em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">)</span></span></span></span></p><p>其中p1~pm是对n进行唯一分解之后的质因子。<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><msub><mi>k</mi><mn>1</mn></msub></msubsup><mo>×</mo><msubsup><mi>p</mi><mn>2</mn><msub><mi>k</mi><mn>2</mn></msub></msubsup><mo>×</mo><mo>…</mo><mo>×</mo><msubsup><mi>p</mi><mi>m</mi><msub><mi>k</mi><mi>m</mi></msub></msubsup></mrow><annotation encoding="application/x-tex">n=p_1^{k_1}\times p_2^{k_2}\times\ldots\times p_m^{k_m}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span>不用去理解为什么是这样，先学会使用它。</p><p>【实现】：求phi(n),这个n范围一般是1-le9,我们利用类似唯一分解的框架去枚举所有质因子按照之前的计算公式去计算即可。后面学习线性筛法后可以筛除一段区间内的所有数字的欧拉函数(例如1~1e7的所有数字的欧拉函数)。示例部分代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> ll = <span class="type">long</span> <span class="type">long</span>;</span><br><span class="line"></span><br><span class="line">ll phi = n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=n/i;i++)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span>(n%i)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    phi = phi/i*(i<span class="number">-1</span>);</span><br><span class="line">    <span class="keyword">while</span>(n%i==<span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        n/=i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(n&gt;<span class="number">1</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        phi = phi/n*(n<span class="number">-1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p><strong>欧拉降幂</strong></p><p>【概念】：首先先介绍欧拉定理，当a,c互质时，有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mrow><mi>ϕ</mi><mo stretchy="false">(</mo><mi>c</mi><mo stretchy="false">)</mo></mrow></msup><mo>=</mo><mn>1</mn><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>c</mi><mo stretchy="false">)</mo></mspace></mspace></mrow><annotation encoding="application/x-tex">a^{\phi(c)}=1\pmod c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">c</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">c</span><span class="mclose">)</span></span></span></span> 由此可知，费马小定理是欧拉定理的特例。</p><p>当a,c互质时有:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mi>b</mi></msup><mo>=</mo><msup><mi>a</mi><mrow><mi>b</mi><mtext> </mtext><mtext>mod</mtext><mtext> </mtext><mi>ϕ</mi><mo stretchy="false">(</mo><mi>c</mi><mo stretchy="false">)</mo></mrow></msup><mtext>mod</mtext><mtext> </mtext><mi>c</mi></mrow><annotation encoding="application/x-tex">a^b=a^{b \,\text{mod} \,\phi(c)} \text{mod} \,c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mspace mtight" style="margin-right:0.1952em;"></span><span class="mord text mtight"><span class="mord mtight">mod</span></span><span class="mspace mtight" style="margin-right:0.1952em;"></span><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">c</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mord text"><span class="mord">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span></span></span></span> ;当a,c不互质时：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>a</mi><mi>b</mi></msup><mo>=</mo><msup><mi>a</mi><mrow><mi>b</mi><mtext> </mtext><mtext>mod</mtext><mtext> </mtext><mi>ϕ</mi><mo stretchy="false">(</mo><mi>c</mi><mo stretchy="false">)</mo><mo>+</mo><mi>ϕ</mi><mo stretchy="false">(</mo><mi>c</mi><mo stretchy="false">)</mo></mrow></msup><mtext>mod</mtext><mtext> </mtext><mi>c</mi></mrow><annotation encoding="application/x-tex">a^b=a^{b \,\text{mod} \,\phi(c)+\phi(c)} \text{mod} \,c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mspace mtight" style="margin-right:0.1952em;"></span><span class="mord text mtight"><span class="mord mtight">mod</span></span><span class="mspace mtight" style="margin-right:0.1952em;"></span><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">c</span><span class="mclose mtight">)</span><span class="mbin mtight">+</span><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">c</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mord text"><span class="mord">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span></span></span></span></p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1155/learning/?page=1&amp;first_category_id=1&amp;problem_id=1155">1.乘积幂次 - 蓝桥云课</a></li></ul><p>设c=1e9+7,本体题目实际上就是要求<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mrow><mi>m</mi><mo stretchy="false">!</mo></mrow></msup><mtext> </mtext><mspace></mspace><mspace width="0.4444em"><mo stretchy="false">(</mo><mrow><mi mathvariant="normal">m</mi><mi mathvariant="normal">o</mi><mi mathvariant="normal">d</mi></mrow><mspace width="0.3333em"><mi>c</mi><mo stretchy="false">)</mo></mspace></mspace></mrow><annotation encoding="application/x-tex">n^{m!} \, \pmod c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mclose mtight">!</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">c</span><span class="mclose">)</span></span></span></span> ,可以利用欧拉降幂进行转化，即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>n</mi><mrow><mi>m</mi><mo stretchy="false">!</mo></mrow></msup><mo>=</mo><msup><mi>n</mi><mrow><mi>m</mi><mo stretchy="false">!</mo><mtext> </mtext><mtext>mod</mtext><mtext> </mtext><mi>ϕ</mi><mo stretchy="false">(</mo><mi>c</mi><mo stretchy="false">)</mo></mrow></msup><mtext>mod</mtext><mtext> </mtext><mi>c</mi></mrow><annotation encoding="application/x-tex">n^{m!}=n^{m! \,\text{mod} \,\phi(c)} \text{mod} \,c</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mclose mtight">!</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mclose mtight">!</span><span class="mspace mtight" style="margin-right:0.1952em;"></span><span class="mord text mtight"><span class="mord mtight">mod</span></span><span class="mspace mtight" style="margin-right:0.1952em;"></span><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">c</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mord text"><span class="mord">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span></span></span></span></p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_18">点击此处</a></p><h3 id="裴蜀定理">裴蜀定理</h3><p>【概念】：又称贝祖定理，即a,b为不全为0的整数，则存在整数x,y使得ax+by=gcd(a,b);</p><p>这里就不写证明了,证明题就留给数学专业的人做吧(●’◡’●)</p><p>【例题引入】：a,b为大于等于0的整数，n为整数，是否存在大于等于0的整数x,y使方程ax+by=n有解？</p><p>这里就不推理了，直接写结论</p><p>若n&gt;ab-a-b，有解；若n=0;有解；若n&lt;0；无解;若ax+by=n有解，则ax+by=ab-a-b-n无解</p><p>【例题】</p><ul><li><p><a href="https://www.lanqiao.cn/problems/1297/learning/?page=1&amp;first_category_id=1&amp;problem_id=1297">1.最小正整数解 - 蓝桥云课</a></p></li><li><p><a href="https://www.lanqiao.cn/problems/213/learning/?page=1&amp;first_category_id=1&amp;problem_id=213">1.买不到的数目 - 蓝桥云课</a></p></li></ul><p>你看这个题目基本上就是例题引入的模板，直接把a，b替换，然后用性质就可以轻松解决</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//对于互质(最大公约为1)的两个数p，q，px+py 不能表示的最大数为pq-p-q.</span></span><br><span class="line">  <span class="type">int</span> a,b;</span><br><span class="line">  cin&gt;&gt;a;</span><br><span class="line">  cin&gt;&gt;b;</span><br><span class="line">  cout&lt;&lt;a * b - a - b; </span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_18">点击此处</a></p><h3 id="素数">素数</h3><h4 id="素数朴素判定与埃氏筛法">素数朴素判定与埃氏筛法</h4><p>【概念】：素数就是质数，素数是指除了1和它本身，没有其他因子的数字，例如7,13,17是质数，而9,14,20不是。为了判断一个数字n是不是质数，我们可以枚举2~-1的所有数字，检查其中是否存在一个数字i可以整除n(即n%i==0)，这是暴力枚举的思想。但是我们又知道，如果a*b=n,不妨设a&lt;b,则有a&lt;=sqrt(n),b&gt;=sqrt(n).于是我们只需要从2枚举到sqrt(n)来判断是否存在n的因子即可。</p><p>【实现】示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">//判定一个数是素数还是非素数</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">isPrime</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (n &lt; <span class="number">2</span>)<span class="comment">//小于2的一定是非素数</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= n / i; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (n % i == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">false</span>;<span class="comment">//i&lt;=n/i等价于i&lt;=sqrt(n)这样就可以防止溢出 </span></span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> num;</span><br><span class="line">cin &gt;&gt; num;</span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">isPrime</span>(num))</span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;是素数&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;不是素数&quot;</span> &lt;&lt; endl;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3334/learning/?page=1&amp;first_category_id=1&amp;problem_id=3334">1.疑似素数 - 蓝桥云课</a> 因为数据量不大，可以用前面的枚举法实现</li></ul><p><strong>埃氏筛法</strong></p><p>【概念】：对于一个合数，它必然存在一个质数的因子，也就是说合数一定是某个较小的质数的倍数。我们知道枚举一个数字n的所有因数是很慢的，是O(sqrt(n)的时间复杂度，那不妨枚举倍数。首先我们知道2是一个质数，然后我们<strong>将2的所有大于它本身的倍数都“筛掉”</strong>，因为可以判定它们都不是质数。然后到3、4…，如果枚举到的数字没有被筛掉，说明在[2~i-1]不存在某个数字可以整除，于是就可以直接<strong>判定是一个质数</strong>，然后再将个所有倍数筛掉。这就是埃氏筛法的思想。也就是<strong>先把所有的非质数筛掉，剩下的就是质数</strong>。</p><blockquote><p>这种方法适合数据量大的题目</p></blockquote><p>【实现】：示例的部分代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> vis[N];<span class="comment">//vis[i]=true，表示i这个被筛选掉了</span></span><br><span class="line">vis[<span class="number">0</span>]=vis[<span class="number">1</span>]=<span class="literal">true</span>;</span><br><span class="line"><span class="comment">//初始化筛选数组</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span>(!vis[i])</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">2</span>*i;j&lt;=n;j+=i)<span class="comment">//开始筛选倍数</span></span><br><span class="line">        &#123;</span><br><span class="line">            vis[j]=<span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3205/learning/?page=1&amp;first_category_id=1&amp;problem_id=3205">1.小明的素数对 - 蓝桥云课</a></li></ul><p>这一题用前面的暴力枚举就会超时，而用埃氏筛选法后再枚举差值判断素数就会好很多</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_19">点击此处</a></p><h4 id="素数筛">素数筛</h4><p>【概念】：<strong>素数筛法是一种快速“筛”出2~n之间所有素数的方法</strong>。朴素的筛法可以根号判断。</p><p>前面我们已经介绍过朴素筛选法和埃氏筛选法，这里我们介绍一个新方法——欧拉筛选法，基本上是埃氏筛选法的优化。</p><p>埃氏筛是筛去每个质数的倍数，但难免，<strong>会有合数会被其不同的质因子多次重复筛去</strong>。这就造成了时间浪费。核心思想：让每一个合数被其最小质因数筛到，所以，我们不需要用一个fo循环去筛除一个质数的所有倍数，我们<strong>将所有质数存储到primes[]中</strong>，然后枚举到第i个数时，就筛去所有的primes[j]*i。这样就在每一次遍历中，正好筛除了所有已知素数的i倍。但是为了确保合数只被最小质因子筛掉，最小质因子要乘以最大的倍数，即要乘以最大的i,所以不能提前筛，所以如果i%primes[j]==0.我们就结束内层循环！</p><p>实际上，对于x，我们遍历到质数表中的p,且发现p|x时，就应当停遍历质数表。具体的证明这里就不写了(●’◡’●)</p><p>【实现】：示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">1e5</span> + <span class="number">7</span>;</span><br><span class="line"><span class="type">int</span> vis[MAXN], isprime[MAXN];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n = <span class="number">100</span>;</span><br><span class="line"><span class="type">int</span> cnt = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (!vis[i])</span><br><span class="line">&#123;</span><br><span class="line">isprime[++cnt] = i;<span class="comment">//存到质数表 </span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= cnt &amp;&amp; isprime[j] * i &lt;= n; j++)</span><br><span class="line">&#123;</span><br><span class="line">vis[isprime[j] * i] = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> (i%isprime[j] == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= cnt; i++)</span><br><span class="line">&#123;</span><br><span class="line">cout &lt;&lt; isprime[i] &lt;&lt; <span class="string">&#x27; &#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】：给定一个区间[a,b]，求区间内有多少个素数</p><p>示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 欧拉筛选法求区间 [a, b] 内的质数个数</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">countPrimesInRange</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (b &lt; <span class="number">2</span>) <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">// 如果 b 小于 2，没有质数</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 初始化标记数组，isPrime[i] 为 true 表示 i 是质数</span></span><br><span class="line">    <span class="function">vector&lt;<span class="type">bool</span>&gt; <span class="title">isPrime</span><span class="params">(b + <span class="number">1</span>, <span class="literal">true</span>)</span></span>;</span><br><span class="line">    isPrime[<span class="number">0</span>] = isPrime[<span class="number">1</span>] = <span class="literal">false</span>; <span class="comment">// 0 和 1 不是质数</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 欧拉筛选法</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= b; ++i) &#123;</span><br><span class="line">        <span class="keyword">if</span> (isPrime[i]) &#123;</span><br><span class="line">            <span class="comment">// 将 i 的倍数标记为非质数</span></span><br><span class="line">            <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">2</span> * i; j &lt;= b; j += i) &#123;</span><br><span class="line">                isPrime[j] = <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 统计区间 [a, b] 内的质数个数</span></span><br><span class="line">    <span class="type">int</span> count = <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = a; i &lt;= b; ++i) &#123;</span><br><span class="line">        <span class="keyword">if</span> (isPrime[i]) &#123;</span><br><span class="line">            ++count;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> count;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="type">int</span> a, b;</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;请输入区间的起始值 a 和结束值 b: &quot;</span>;</span><br><span class="line">    cin &gt;&gt; a &gt;&gt; b;</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> primeCount = <span class="built_in">countPrimesInRange</span>(a, b);</span><br><span class="line">    cout &lt;&lt; <span class="string">&quot;区间 [&quot;</span> &lt;&lt; a &lt;&lt; <span class="string">&quot;, &quot;</span> &lt;&lt; b &lt;&lt; <span class="string">&quot;] 内的质数个数为: &quot;</span> &lt;&lt; primeCount &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="唯一分解定理">唯一分解定理</h3><p>【概念】：唯一分解定理(就是<strong>质因数分解</strong>)指的是：对于任意一个&gt;1的正整数，都可以以唯一的一种方式分解为若干质因数的乘积。<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><msub><mi>k</mi><mn>1</mn></msub></msubsup><mo>×</mo><msubsup><mi>p</mi><mn>2</mn><msub><mi>k</mi><mn>2</mn></msub></msubsup><mo>×</mo><mo>…</mo><mo>×</mo><msubsup><mi>p</mi><mi>m</mi><msub><mi>k</mi><mi>m</mi></msub></msubsup></mrow><annotation encoding="application/x-tex">n=p_1^{k_1}\times p_2^{k_2}\times\ldots\times p_m^{k_m}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span> 这个式子中的p1,p2是类似2,3,5,7这样的质数。将单个数字进行质因数方法是，从小到大枚举x的所有可能的质因子，最大枚举到sqt(),每遇到一个可以整除的数字，就不断进行除法直到除尽。最后如果还有x&gt;1,说明还有一个较大的质因子。</p><p>【实现】</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">2e5</span><span class="number">+9</span>;</span><br><span class="line"></span><br><span class="line">vector&lt;pair&lt;<span class="type">int</span>,<span class="type">int</span>&gt;&gt;v;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> x;</span><br><span class="line">cin&gt;&gt;x;</span><br><span class="line"><span class="comment">//枚举所有可能的质因子</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=x/i;i++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//如果不能整除直接跳过</span></span><br><span class="line"><span class="keyword">if</span>(x%i) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//如果可以整除，那么必然是一个质因子</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//cnt表示当亲爱这个质因子i的指数</span></span><br><span class="line"><span class="type">int</span> cnt = <span class="number">0</span>;</span><br><span class="line"><span class="comment">//一直除，直到除干净</span></span><br><span class="line"><span class="keyword">while</span>(x%i == <span class="number">0</span>) </span><br><span class="line">&#123;</span><br><span class="line">cnt++;</span><br><span class="line">x/=i;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(x&gt;<span class="number">1</span>)</span><br><span class="line">&#123;</span><br><span class="line">v.<span class="built_in">push_back</span>(&#123;x,<span class="number">1</span>&#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> i:v)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;i.first&lt;&lt;<span class="string">&#x27; &#x27;</span>&lt;&lt;i.second&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>约数个数定理</strong></p><p>通过某个数字的唯一分解： <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><msub><mi>k</mi><mn>1</mn></msub></msubsup><mo>×</mo><msubsup><mi>p</mi><mn>2</mn><msub><mi>k</mi><mn>2</mn></msub></msubsup><mo>×</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>×</mo><msubsup><mi>p</mi><mi>m</mi><msub><mi>k</mi><mi>m</mi></msub></msubsup></mrow><annotation encoding="application/x-tex">x = p_1^{k_1} \times p_2^{k_2} \times ... \times p_m^{k_m}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span>  我们可以求出x的约数(因数)个数，如果学过线性代数或者有向量相关的知识的话，可以理解 为将不同的质因子看作是不同的向量空间或基底，不同质因子之间互不干扰。也就是说p1的指数的取值是[0,k1]共(k1+1)个，p2,p3…亦然，所以x的约数的个数就是 (k1+1) * (k2+1) *…(km+1)，即：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msubsup><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo stretchy="false">(</mo><msub><mi>k</mi><mi>i</mi></msub><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">d(x)=\prod_{i=1}^m(k_i+1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.104em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∏</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1020/learning/?page=1&amp;first_category_id=1">0阶乘约数 - 蓝桥云课</a></li></ul><p>100的阶乘约数个数就是所有(质因数的指数+1)的乘积</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_19">点击此处</a></p><p><strong>约数和定理</strong></p><p>通过某个数字的唯一分解: <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><msub><mi>k</mi><mn>1</mn></msub></msubsup><mo>×</mo><msubsup><mi>p</mi><mn>2</mn><msub><mi>k</mi><mn>2</mn></msub></msubsup><mo>×</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>×</mo><msubsup><mi>p</mi><mi>m</mi><msub><mi>k</mi><mi>m</mi></msub></msubsup></mrow><annotation encoding="application/x-tex">x = p_1^{k_1} \times p_2^{k_2} \times ... \times p_m^{k_m}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span> 我们可以求出<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi></mrow><annotation encoding="application/x-tex">x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span>的约数(因数)之和，与约数个数定理类似。p1对于约数和的贡献为1或p1或<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><msup><mn>1</mn><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">p1^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span>或…或<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><msup><mn>1</mn><msub><mi>k</mi><mn>1</mn></msub></msup></mrow><annotation encoding="application/x-tex">p1^{k_1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mord"><span class="mord">1</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>，于是x的约数之和可以表达为:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>u</mi><mi>m</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>=</mo><msubsup><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>m</mi></msubsup><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>0</mn></mrow><msub><mi>k</mi><mi>i</mi></msub></msubsup><msubsup><mi>p</mi><mi>i</mi><mi>j</mi></msubsup></mrow><annotation encoding="application/x-tex">sum(x) = \prod_{i=1}^{m} \sum_{j=0}^{k_i} p_i^j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">m</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4248em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∏</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.989em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9426em;"><span style="top:-2.4231em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2769em;"><span></span></span></span></span></span></span></span></span></span></p><h3 id="行列式">行列式</h3><p>【概念】：线性代数第一章的知识点，不懂的看宋浩的线性代数</p><p>行列式，记作det A或|A|。行列式定义如下：  <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>A</mi><mi mathvariant="normal">∣</mi><mo>=</mo><msub><mo>∑</mo><mi>p</mi></msub><mo stretchy="false">(</mo><mo>−</mo><mn>1</mn><msup><mo stretchy="false">)</mo><mrow><mi>τ</mi><mo stretchy="false">(</mo><mi>p</mi><mo stretchy="false">)</mo></mrow></msup><msubsup><mo>∏</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><msub><mi>p</mi><mi>i</mi></msub></mrow></msub></mrow><annotation encoding="application/x-tex">|A|=\sum_{p}(-1)^{\tau(p)}\prod_{i=1}^{n}a_{i,p_i}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">A</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.3238em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.0017em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">1</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.1132em;">τ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">p</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∏</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>其中，A必须为n×n的方阵，p为n的排列，τ(p)为排列p的逆序数。<strong>不用记这个公式，按照线性代数中的例子去理解就行</strong>。</p><p>【性质】</p><p><strong>代数余子式</strong>: 对于行列式|A|将其第行第ⅰ列的所有元素删除，剩下的部分组成的行列式，再乘以<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mo>−</mo><mn>1</mn><msup><mo stretchy="false">)</mo><mrow><mi>i</mi><mo>+</mo><mi>j</mi></mrow></msup></mrow><annotation encoding="application/x-tex">(-1)^{i+j}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0747em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">1</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span></span></span></span></span></span></span></span>,叫做元素<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">a_{i,j}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>,的代数余子式，记作<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">A_{i,j}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>,</p><p>【定理】：</p><ul><li>⭐⭐⭐(重要) 行列式展开：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi mathvariant="normal">∣</mi><mi>A</mi><mi mathvariant="normal">∣</mi><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub><msub><mi>A</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">|A| = \sum^{n}_{j=1}a_{i,j}A_{i,j};</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord mathnormal">A</span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2401em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">;</span></span></span></span>              <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><msub><mi>a</mi><mrow><mi>i</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub><msub><mi>A</mi><mrow><mi>k</mi><mo separator="true">,</mo><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">0 = \sum^{n}_{j=1}a_{i,j}A_{k,j}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2401em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></li><li>矩阵A的某一行（列）乘以k加到另一行（列），其行列式不变</li><li>矩阵A的某一行（列）乘以k,行列式的值=k|A|</li><li>矩阵A任意两行或两列互换，行列式的值等于其相反数</li></ul><p>【实现】</p><p>就是前面讲过的高斯消元法，这里我用C++中的vector容器实现</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">double</span> <span class="title">det</span><span class="params">(<span class="type">int</span> n, vector&lt;vector&lt;<span class="type">double</span>&gt;&gt; &amp;a, <span class="type">const</span> <span class="type">double</span> EPS)</span> </span>&#123;</span><br><span class="line">    <span class="type">double</span> det = <span class="number">1</span>; <span class="comment">// 初始化行列式的值为 1</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 高斯消元法主循环</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">        <span class="type">int</span> tmp = i; <span class="comment">// 记录当前列中绝对值最大的行索引</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// 寻找第 i 列中绝对值最大的元素所在的行</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = i + <span class="number">1</span>; j &lt; n; j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (<span class="built_in">fabs</span>(a[j][i]) &gt; <span class="built_in">fabs</span>(a[tmp][i])) &#123;</span><br><span class="line">                tmp = j;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 如果当前列的最大绝对值小于 EPS，说明矩阵是奇异的，行列式为 0</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">fabs</span>(a[tmp][i]) &lt; EPS) &#123;</span><br><span class="line">            det = <span class="number">0</span>;</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 如果最大绝对值不在当前行，交换两行，并更新行列式的符号</span></span><br><span class="line">        <span class="keyword">if</span> (tmp != i) &#123;</span><br><span class="line">            <span class="built_in">swap</span>(a[tmp], a[i]);</span><br><span class="line">            det *= <span class="number">-1</span>; <span class="comment">// 交换行时，行列式需要乘以 -1</span></span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 对当前列下方的元素进行消元</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt; n; j++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (j != i &amp;&amp; <span class="built_in">fabs</span>(a[j][i]) &gt; EPS) &#123; <span class="comment">// 跳过当前行，对其他行进行消元</span></span><br><span class="line">                <span class="type">double</span> res = a[j][i]; <span class="comment">// 记录消元系数</span></span><br><span class="line">                <span class="keyword">for</span> (<span class="type">int</span> k = i; k &lt; n; k++) &#123;</span><br><span class="line">                    a[j][k] -= a[i][k] * res / a[i][i]; <span class="comment">// 消元操作</span></span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 更新行列式的值</span></span><br><span class="line">        det *= a[i][i];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> det; <span class="comment">// 返回行列式的值</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="排列组合">排列组合</h3><blockquote><p>就是高中的组合与全排列，以下不侧重其概念的解释，而是讲解其性质和应用</p></blockquote><p>【性质】：</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mtable rowspacing="0.25em" columnalign="right left" columnspacing="0em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><msubsup><mi>C</mi><mi>n</mi><mi>m</mi></msubsup><mo>=</mo><mfrac><mrow><mi>n</mi><mo>×</mo><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>2</mn><mo stretchy="false">)</mo><mo>×</mo><mo>…</mo><mo>×</mo><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><mrow><mi>m</mi><mo>×</mo><mo stretchy="false">(</mo><mi>m</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mo stretchy="false">(</mo><mi>m</mi><mo>−</mo><mn>2</mn><mo stretchy="false">)</mo><mo>×</mo><mo>…</mo><mo>×</mo><mn>1</mn></mrow></mfrac><mo>=</mo><mfrac><mrow><mi>n</mi><mo stretchy="false">!</mo></mrow><mrow><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mi>m</mi><mo stretchy="false">)</mo><mo stretchy="false">!</mo><mi>m</mi><mo stretchy="false">!</mo></mrow></mfrac></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><msubsup><mi>C</mi><mi>n</mi><mn>0</mn></msubsup><mo>+</mo><msubsup><mi>C</mi><mi>n</mi><mn>1</mn></msubsup><mo>+</mo><msubsup><mi>C</mi><mi>n</mi><mn>2</mn></msubsup><mo>+</mo><mo>…</mo><mo>+</mo><msubsup><mi>C</mi><mi>n</mi><mi>n</mi></msubsup><mo>=</mo><msup><mn>2</mn><mi>n</mi></msup><mspace width="1em"><msubsup><mi>A</mi><mi>n</mi><mi>n</mi></msubsup><mo>=</mo><mi>n</mi><mo stretchy="false">!</mo></mspace></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><msubsup><mi>C</mi><mi>n</mi><mi>m</mi></msubsup><mo>=</mo><msubsup><mi>C</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><mi>m</mi></msubsup><mo>+</mo><msubsup><mi>C</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow><mrow><mi>m</mi><mo>−</mo><mn>1</mn></mrow></msubsup></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{aligned} &amp; C_n^m=\frac{n\times(n-1)\times(n-2)\times\ldots\times(n-m+1)}{m\times(m-1)\times(m-2)\times\ldots\times1}=\frac{n!}{(n-m)!m!} \\ &amp; C_n^0+C_n^1+C_n^2+\ldots+C_n^n=2^n\quad A_n^n=n! \\ &amp; C_n^m=C_{n-1}^m+C_{n-1}^{m-1}\end{aligned}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:5.7112em;vertical-align:-2.6056em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.1056em;"><span style="top:-5.1056em;"><span class="pstrut" style="height:3.427em;"></span><span class="mord"></span></span><span style="top:-3.0055em;"><span class="pstrut" style="height:3.427em;"></span><span class="mord"></span></span><span style="top:-1.4814em;"><span class="pstrut" style="height:3.427em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.6056em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.1056em;"><span style="top:-5.1056em;"><span class="pstrut" style="height:3.427em;"></span><span class="mord"><span class="mord"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">2</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">2</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">m</span><span class="mclose">)!</span><span class="mord mathnormal">m</span><span class="mclose">!</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mclose">!</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.0055em;"><span class="pstrut" style="height:3.427em;"></span><span class="mord"><span class="mord"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">n</span><span class="mclose">!</span></span></span><span style="top:-1.4814em;"><span class="pstrut" style="height:3.427em;"></span><span class="mord"><span class="mord"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3053em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.4436em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3148em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.6056em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>分类加法</strong></p><p>在组合计数中，如果可以将要计数的东西划分为多个互不影响的类别，那么在计算出每一类的数量后，最终结果是各类别的数量相加。比如从迷宫入口走到出口一共有几条路，一般来说只要各路径之间不完全重合，符合题意就可以作为一条路，不同的路相加就是总路数。</p><p>分类加法的计数原理往往运用在<strong>计数dp</strong>中，具体表现在状态转移方程为dp[i]=若干个类别的状态的求和。这种计数dp的状态转移方程就是由<strong>分类加法原理</strong>导出的。比如将向下走的和向右边走的分一类，向下走的又可以分成几类，以此类推。</p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/3347/learning/?page=1&amp;first_category_id=1&amp;problem_id=3347">1.机器人的选法总数 - 蓝桥云课</a></li></ul><p>先不要进入到代码中，从做数学题的角度来看，就是要你求符合提议的数，正向考虑比较麻烦，可以考虑反向思考，即总数-不符合题意的数=符合题意的数，即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mi>n</mi></msup><mo>−</mo><msubsup><mi>C</mi><mi>n</mi><mi>a</mi></msubsup><mo>−</mo><msubsup><mi>C</mi><mi>n</mi><mi>b</mi></msubsup><mo>−</mo><msubsup><mi>C</mi><mi>n</mi><mn>0</mn></msubsup></mrow><annotation encoding="application/x-tex">2^n-C_n^a-C_{n}^b-C_{n}^{0}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7477em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9303em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0611em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">0</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span></p><ul><li><a href="https://www.lanqiao.cn/problems/3197/learning/?page=1&amp;first_category_id=1&amp;problem_id=3197">1.方格染色 - 蓝桥云课</a></li></ul><p>通过观察分析我们发现，如果要使得方格染色合法，第一行或第一列一定是两种颜色交替出现的。设集合A:第一行交替出现的方案<br>数；集合B:第一列交替出现的方案数。于是答案AUB=A+B-A∩B</p><p><strong>分步乘法</strong></p><p>原理的出现频率并没有分类加法高，但也依然是十分重要的计数原理**。当为了构造某一个东西需要许多步，且每一步互不影响**、有多种选择时，总的方案数就是各步的选择数的乘积。例如我要求一个整数的因子数量，除了一个个枚举的方法，我们还可以先将其进行唯一分解，然后进行构造。 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>=</mo><msubsup><mi>p</mi><mn>1</mn><msub><mi>k</mi><mn>1</mn></msub></msubsup><mo>×</mo><msubsup><mi>p</mi><mn>2</mn><msub><mi>k</mi><mn>2</mn></msub></msubsup><mo>×</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>×</mo><msubsup><mi>p</mi><mi>m</mi><msub><mi>k</mi><mi>m</mi></msub></msubsup></mrow><annotation encoding="application/x-tex">n = p_1^{k_1} \times p_2^{k_2} \times ... \times p_m^{k_m}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0961em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span>的因子的个数其实就是m元组(t1,t2,tm)的个数，其中ti的取值范围是[0,ki]并且元组中各项都满足互不影响的原则。那么我们就可以求到n的因子的个数是k1+1) * (k2+1) * … *(km+1).<strong>这种题目你也做过，就是高中的填色问题</strong>。</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_20">点击此处</a></p><h2 id="参考">参考</h2><ol><li><a href="https://leetcode.cn/circle/discuss/E3yavq/">力扣刷题攻略</a>  读者可以在这里参考刷题。</li><li>蓝桥云课C++班，作者谢子杨</li></ol>]]></content>
    
    
    <summary type="html">总结了C/C++赛道蓝桥杯常见的题型以及背后的算法原理,为读者提供一个刷题和总结的参考。</summary>
    
    
    
    <category term="algorithm" scheme="https://lloydkai.cn/categories/algorithm/"/>
    
    
    <category term="C" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>算法系列(三)蓝桥杯_算法高阶(一)</title>
    <link href="https://lloydkai.cn/posts/lanqiaocup-series-three/"/>
    <id>https://lloydkai.cn/posts/lanqiaocup-series-three/</id>
    <published>2025-02-10T05:15:23.000Z</published>
    <updated>2026-04-23T01:45:04.975Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/rVx9ogHB31wf4mJ.jpg" alt></p><h1>算法高阶</h1><blockquote><p>本部分算法难度较高，建议读者充分掌握算法基础之后再来学习。</p><p>目前以视频的方法为主，等蓝桥杯考完之后按照labuladong或者是考研的方法写代码。</p></blockquote><h2 id="我的仓库使用指南">我的仓库使用指南</h2><p>我的仓库链接格式如下：<code>https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/1_20</code> 其中1_20表示的是日期(一般是2025)，里面的文件就包含对应题目的解答(均通过对应题目的测试)或者是算法实现，其中文件名<code>lanqiao</code>表示 是<strong>蓝桥杯官网上的题目</strong>，<code>_</code> 后面的数字是蓝桥杯的<strong>题目编号</strong>，可以找到对应的蓝桥杯的题目，比如题目链接是<code>https://www.lanqiao.cn/problems/498/learning/?page=1&amp;first_category_id=1&amp;problem_id=498</code>    <code>problems</code>斜杠后面的数字<strong>498</strong> 就是对应的题目编号，你就在我指定链接下面的文件夹下按照<code>lanqiao_题目编号.cpp</code> 这样的格式找对应文件，就可以看到对应题目的解答代码。</p><p><img src="https://s2.loli.net/2025/02/06/n4dH1aOXoCc35Sy.png" alt="001_demo.png"></p><hr><h2 id="搜索">搜索</h2><h3 id="回溯法">回溯法</h3><p>【概念】：回溯法一般使用DFS(深度优先搜索)实现，DFS是一种遍历或搜索图、树或图像等数据结构的算法，当然这个图、树未必要存储下来(隐式处理就是回溯法)，常见的是通过某种关系构造出的搜索树，搜索树一般是排列型搜索树(总节点个数一般为n!级别)和子集型搜索树(总节点个数一般为2^n级别)。</p><p>排列型就是每次枚举选哪个，子集型就是对于每一个元素选或不选(结果与顺序无关)。DFS从起始节点开始，沿着一条路径尽可能深入地搜索(一条路走到黑)，直到无法继续为止，然后回溯到前一个节点，继续探索其他路径，直到遍历完整个图或树。DFS使用栈或递归来管理节点的遍历顺序，一般使用递归。很多时候DFS和回溯法不必过度区分。</p><p>【实现】实际上的回溯法比较灵活，需要根据题意要求来具体分析。vis[i]表示数字i是否使用过，也经常被用于表示<br>某个元素是否使用过a[]]存放结果，当dep深度=n+1时说明n层都已经算完了，直接输出结果。子集型搜索树模板结构类似，就是在往下走时候只有两条边，表示“选或不选当前这个元素</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1508/learning/?page=1&amp;first_category_id=1&amp;problem_id=1508">1.N皇后问题 - 蓝桥云课</a> 非常经典的题目</li></ul><p>【分析】：首先可以肯定的是，每一行必然有且仅有一个皇后（因为不可能出现两个皇后在同一行），于是就通过<strong>枚举每一层皇后的位置</strong>来搜索所有可能解即可。每放置一个皇后就将对应的米字型区域设置为“禁区”(vis[]数组)，后面的皇后就不能放在“禁区”里，回溯的时候将禁区取消掉。为了正确维护“禁区”，不能使用bool数组来表示禁区，需要使用int数组，表示这个位置被“多少个皇后占用了”，当占用数为0时表示“禁区解除”。<strong>层数到n+1时表示找到了一个解，不可行的解都到不了第n+1层</strong></p><ul><li><a href="https://www.lanqiao.cn/problems/182/learning/?page=1&amp;first_category_id=1&amp;problem_id=182">1.小朋友崇拜圈 - 蓝桥云课</a></li></ul><p>跑dfs求最大的环，可以用时间戳(dfn)，将走过的地方标记一个时间戳（即第几步走到的）后续搜索中，每次开始时更新最小时<br>戳 (mindfn)，如果走到已经走过的点就必须停下，然后根据时间戳的合法性来更新最大值。</p><ul><li><a href="https://www.lanqiao.cn/problems/178/learning/?page=1&amp;first_category_id=1&amp;problem_id=178">1.全球变暖 - 蓝桥云课</a></li></ul><p>这里直接统计岛屿的数量比较复杂，可以将不同的岛屿标记(先用dfs将不同的岛屿染上不同的颜色)，然后计算最后剩下的岛屿颜色有多少种，再减去就是被淹没的岛屿数量。</p><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_10">点击此处</a></p><h3 id="剪枝">剪枝</h3><p>【概念】：剪枝更偏向于技巧性，是对回溯法的优化。其实就是将搜索过程当中一些不必要的部分直接剔除掉，因为搜索过程构成了一棵树，剔除不必要的部分，就像是在树上将树枝剪掉，故名剪枝。</p><p>在实际使用中剪枝是通过一些约束条件使得<strong>搜索提前终止</strong>实现的。</p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/2942/learning/?page=1&amp;first_category_id=1&amp;problem_id=2942">1.数字王国之军训排队 - 蓝桥云课</a> 如果这一题不使用剪枝的方法就会导致最后一个测试用例超时</li></ul><p>在做这一类题的时候，关键在于将“若干””队“等词语<strong>理解成树的每一层</strong>(你想想看是不是这样)而不是简单的多个数组，那么就会自然而然想到使用DFS解决问题。注意树一般是用二维数组数据结构来存储的。</p><ul><li><a href="https://www.lanqiao.cn/problems/3008/learning/?page=1&amp;first_category_id=1&amp;problem_id=3008">1.特殊的三角形 - 蓝桥云课</a></li></ul><p>不妨规定我们构造出的3元组是递增的，那么在搜索过程中我们就可以通过计算得到当前这个位置的上限（剪枝的关键dfs过程中记录乘积，因为乘得越多数字越大，当乘积mul&gt;1e6时直接返回（乘积很容易就超过1e5,数字较大时层数就两三层）同时还能记录一下n-1条边的长度和sum,最后一条边必须小于sum.最后用前缀和快速进行区间查询。</p><ul><li><a href="https://www.lanqiao.cn/problems/3075/learning/?page=1&amp;first_category_id=1&amp;problem_id=3075">1.特殊的多边形 - 蓝桥云课</a> 方法和特殊的三角形一样 这道题的通用性比上一题更强。</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_11">点击此处</a></p><h3 id="记忆性搜索-带备忘录的搜索">记忆性搜索(带备忘录的搜索)</h3><p>【概念】：就是将搜索过程中会重复计算且结果相同的部分保存下来，作为一个状态，下次访问到这个状态时直接将这个子搜索的结果返回，而不需要再重新算一遍。通常会使用数组或map来进行记忆化，下标一般和dfs的参数表对应。需要注意的是使用记忆化需要保证重复计算的结果是相同的，否则可能产生数据失真。</p><p>【例题】：</p><ul><li>斐波那契数列对1e9+7取模。如果使用传统的递归可以做，但是如果要求的位很大的话会超时。我们可以观察到每一次计算某一位的斐波那契值的时候都把前面计算过的又计算了一遍，存在重复计算的现象，不妨将重复计算的值存储起来，下次要使用的时候如果有就直接使用，这样大大减少时间。</li></ul><p>示例代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll;</span><br><span class="line"><span class="type">const</span> ll p =<span class="number">1e7</span>;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> inf = <span class="number">1e9</span>,N = <span class="number">1e5</span><span class="number">+3</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//备忘录数组</span></span><br><span class="line">ll dp[N] ;</span><br><span class="line"></span><br><span class="line"><span class="function">ll <span class="title">f</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(n&lt;=<span class="number">2</span>) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//如果备忘录数组中已经记录过对应的值</span></span><br><span class="line"><span class="keyword">if</span>(dp[n]!=<span class="number">-1</span>) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> dp[n];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> dp[n] = (<span class="built_in">f</span>(n<span class="number">-1</span>)+<span class="built_in">f</span>(n<span class="number">-2</span>)) %p;</span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化备忘录，-1表示没有被初始化</span></span><br><span class="line"><span class="built_in">memset</span>(dp,<span class="number">-1</span>,<span class="built_in">sizeof</span>(dp));</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line">cout&lt;&lt;<span class="built_in">f</span>(n)&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3820/learning/?page=1&amp;first_category_id=1&amp;problem_id=3820">1.混境之地5 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/216/learning/?page=1&amp;first_category_id=1&amp;problem_id=216">1.地宫取宝 - 蓝桥云课</a></li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_11">点击此处</a></p><hr><h2 id="动态规划">动态规划</h2><h3 id="背包问题">背包问题</h3><p>【概念介绍】：<strong>01背包模型</strong>：有一个体积为V的背包，商店有个物品，每个物品有一个价值v和体积w,每个物品只能被拿一次，问能够装下物品的最大价值。</p><p>【实现】：这里每一种物品只有两种状态即“拿”或“不拿”。设<strong>状态dp[i][j]表示到第i个物品为止，拿的物品总体积为j的情况下的最大价值</strong>。我们并不关心某个物品有没有被拿，<strong>只关心当前体积下的最大价值</strong>。转移方程为：<code>dp[i][j]=max(dp[i-1][j],dp[i-1][j-w]+v);</code>如果不拿物品i,那么最大价值就是<code>dp[i-1][j]</code>,如果拿了就是从体积j-w转移过来，体积会变大w,价值增加v最后输出<code>dp[n][V]</code>；</p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/1174/learning/?page=1&amp;first_category_id=1&amp;problem_id=1174">1.小明的背包1 - 蓝桥云课</a></li></ul><p>通用解法</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> dp[<span class="number">1010</span>][<span class="number">1010</span>];</span><br><span class="line"><span class="type">int</span> v[<span class="number">1010</span>], w[<span class="number">1010</span>];<span class="comment">//价值和体积</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> N, V;</span><br><span class="line">cin &gt;&gt; N &gt;&gt; V;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= N; i++) <span class="comment">//把下标0空出来</span></span><br><span class="line">&#123;</span><br><span class="line">cin &gt;&gt; w[i] &gt;&gt; v[i];<span class="comment">//初始化数组</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//开始dp动态规划</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= N; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">1</span>; j &lt;= V; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (w[i] &gt; j) <span class="comment">// 如果物品的体积大于背包的</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//那么最优解就是没选这个物品</span></span><br><span class="line">dp[i][j] = dp[i - <span class="number">1</span>][j];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> <span class="comment">//如果物品的体积小于背包</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//转移方程</span></span><br><span class="line">dp[i][j] = <span class="built_in">max</span>(dp[i - <span class="number">1</span>][j], dp[i - <span class="number">1</span>][j - w[i]] + v[i]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//输出结果</span></span><br><span class="line">cout &lt;&lt; dp[N][V] &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>01背包的优化</strong>：首先有<code>dp[i][j]=dp[i-l][j]</code>,相当于将dp[i-1]复制给dp[i],然后<code>dp[i][j]=max(dp[i][j],dp[i-1][j-w]+v)</code>,每次的下标都是从小的转移到大的，于是我们可以将第一维度给优化掉，直接当做个数组，然后每次更新时，从后往前更新，这样避免了用新数据来更新新数据。即变为：<code>dp[j]=max(dp[j],dp[j-w]+v)</code>,dp[j]表示此时物品总重量为j的情况下的最大价值</p><p>优化后的代码</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">105</span>,M = <span class="number">1010</span>;</span><br><span class="line">ll dp[M];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="type">int</span> n,V;</span><br><span class="line">  cin&gt;&gt;n&gt;&gt;V;</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    ll w,v;</span><br><span class="line">    cin&gt;&gt;w&gt;&gt;v;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> j = V;j&gt;=w;j--)</span><br><span class="line">    &#123;</span><br><span class="line">      dp[j] = <span class="built_in">max</span>(dp[j],dp[j-w]+v);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  cout&lt;&lt;dp[V]&lt;&lt;<span class="string">&quot;\n&quot;</span>;</span><br><span class="line">  </span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><a href="https://www.lanqiao.cn/problems/2223/learning/?page=1&amp;first_category_id=1&amp;problem_id=2223">1.背包与魔法 - 蓝桥云课</a> 对于每个物品有3种选择，可以不选、选但不用魔法、选且用魔法。有点像是之前的那个喷气背包题目</li></ul><p>背包问题的解决代码很少，但是其中蕴含的算法和数学思想很多，读者需要多写多理解才能体会其中的精神。</p><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_11">点击此处</a></p><h3 id="单调队列多重背包">单调队列多重背包</h3><p>【介绍】：有N种物品和一个容量是V的背包，每种物品数量有限,第i件物品的体积为v[i]，价值为w[i]，数量为s[i].求解将哪些物品装入背包使得总价值最大</p><p>【实现】：最简单的实现(基础版模型) 多重背包就是将每种物品的s个摊开，变为s种相同的物品，从而退化成01背包问题</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> maxn 110</span></span><br><span class="line"><span class="type">int</span> n, m, v[maxn], w[maxn],s[maxn];</span><br><span class="line"><span class="type">int</span> f[maxn][maxn];</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//第一种多重背包的算法实现</span></span><br><span class="line"><span class="comment">//虽然简单，但时间复杂度很高O(n*v*s)，基本上在数据量很小的时候才能使用 </span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化数据 </span></span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>, &amp;n, &amp;m);</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d%d&quot;</span>, &amp;v[i], &amp;w[i], &amp;s[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//开始动态规划</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = <span class="number">0</span>; j &lt;= m; j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">0</span>; k &lt;= s[i]; k++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (j &gt;= w[i] * k)</span><br><span class="line">&#123;</span><br><span class="line">f[i][j] = f[i - <span class="number">1</span>][j - w[i] * k] + v[i] * k;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; f[n][m] &lt;&lt; endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【优化】：二进制优化，多重背包基础模型的时间复杂度为<code>O(n*s*V)</code>,<strong>当s较大时，容易超时</strong>。为了解决这个问题，我们可以在“<strong>拆分</strong>”操作时进行一些优化，我们不再是拆分成均为1个物品的组，而是每一组的物品个数为1、2、4、8…，最后剩下的单独为一组，这样一定存在<br>一种方案来表示0~s的所有情况（想象二进制数的表示方法）在经典模型中，一种物品将被拆分为s组，每组一个，而二进制优化模型中，一种物品将被拆分为约log2(s)组，其中每组个数为1、2、4、8…，例如s=11,将被拆为s=1+2+4+4。这样对拆分后的物品<strong>跑一遍01背包</strong>即可，时间复杂度为<code>O(n*log(s)*V)</code>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cctype&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> maxn 110</span></span><br><span class="line"><span class="type">int</span> n, m, v[maxn], w[maxn],s[maxn];</span><br><span class="line"><span class="type">int</span> f[maxn];</span><br><span class="line"></span><br><span class="line"><span class="comment">//创建商品的结构体(或者类也可以)</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Goods</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> w, v;</span><br><span class="line">&#125;;</span><br><span class="line">vector&lt;Goods&gt;goods;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 第二种多重背包的算法实现</span></span><br><span class="line"><span class="comment">//利用二进制的方法实现优化(比如将7看作是110,就是4个i与3个i ，也就是7件 </span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化数据 </span></span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>, &amp;n, &amp;m);</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d%d&quot;</span>, &amp;v[i], &amp;w[i], &amp;s[i]);</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">1</span>; k &lt;= s[i]; k++)</span><br><span class="line">&#123;</span><br><span class="line">s[i] = k;</span><br><span class="line">goods.<span class="built_in">push_back</span>(&#123; w[i] * k, v[i] * k &#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (s[i] &gt; <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line">goods.<span class="built_in">push_back</span>(&#123; s[i] * w[i],s[i] * v[i] &#125;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; goods.<span class="built_in">size</span>(); i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = m; j &gt;= goods[i].w; j--)</span><br><span class="line">&#123;</span><br><span class="line">f[j] = <span class="built_in">max</span>(f[j], f[j - goods[i].w] + goods[i].v);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; f[n] &lt;&lt; endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看到，以上算法在时间复杂度上没有优势，那么有没有什么方法能够较好的解决多重背包的问题呢？<br>当然是有的，就是接下来要讲的单调队列。</p><p>【引入】：<code>dp[i][j]</code>表示将前i种物品放入容量为j的背包中所得到的最大价值<code>dp[i][j]</code>=max(不放入物品i,放入1个物品i,放入2个物品i,.,放入k个物品i) 这里k要满足：k&lt;=s,j-k * v&gt;=0.</p><p>在不放物品的情况下<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>=</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">i=dp[i-1][j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span></span></span></span><br>放k个物品<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>=</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo>−</mo><mi>k</mi><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo>+</mo><mi>k</mi><mo>∗</mo><mi>w</mi></mrow><annotation encoding="application/x-tex">i=dp[i-1][j-k*v]+k*w</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span></span></span></span><br>推导可得<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo>−</mo><mi>v</mi><mo stretchy="false">]</mo><mo>+</mo><mi>w</mi><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo>−</mo><mn>2</mn><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo>+</mo><mn>2</mn><mo>∗</mo><mi>w</mi><mo separator="true">,</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo>−</mo><mi>k</mi><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo>+</mo><mi>k</mi><mo>∗</mo><mi>w</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">dp[i][j]=max(dp[i-1][j],dp[i-1][j-v]+w,dp[i-1][j-2*v]+2*w,...,dp[i-1][j-k*v]+k*w)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">...</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mclose">)</span></span></span></span><br>一维可以滚掉.假设一共有m容量，那么答案为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>n</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>m</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[n][m]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">n</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">m</span><span class="mclose">]</span></span></span></span></p><p>接下来，我们把dp[0]-&gt;dp[m]写成下面这种形式<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mn>2</mn><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mn>3</mn><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mo>…</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>k</mi><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mn>2</mn><mo>∗</mo><mi>v</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mn>3</mn><mo>∗</mo><mi>v</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>k</mi><mo>∗</mo><mi>v</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[0],dp[v],dp[2*v],dp[3*v],…,dp[k*v],dp[1],dp[v+1],dp[2*v+1],dp[3*v+1],...dp[k*v+1]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">...</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span></span></span></span></p><p>m一定等于k * v+j,其中0&lt;=j&lt;v,所以，我们可以把dp数组分成j个类，每一类中的值，都是在同类之间转换得到的<br>也就是说，<code>dp[k*v+j]</code>订只依赖于<code>&#123;dp[j],dp[v+j],dp[2*v+j],dp[3*v+j]…,dp[k*v+j]&#125;</code>因为我们需要的是<code>&#123;dp[j],dp[v+j],dp[2*v+j],dp[3*v+j],…,dp[k*v+j&#125;</code>中的最大值，可以通过维护一个单调队列来得到结果。这样的话，问题就变成了一个单调队列的问题。其中</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">dp[j]=dp[i];</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mpunct">;</span></span></span></span><br><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo>+</mo><mi>v</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo>+</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">]</mo><mo>−</mo><mi>w</mi><mo stretchy="false">)</mo><mo>+</mo><mi>w</mi><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">dp[j+v]=max(dp[j],dp[j+v]]-w)+w;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mpunct">;</span></span></span></span><br><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo>+</mo><mn>2</mn><mi>v</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo>+</mo><mi>v</mi><mo stretchy="false">]</mo><mo>−</mo><mi>w</mi><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo>+</mo><mn>2</mn><mi>v</mi><mo stretchy="false">]</mo><mo>−</mo><mn>2</mn><mi>w</mi><mo stretchy="false">)</mo><mo>+</mo><mn>2</mn><mi>w</mi><mo separator="true">;</mo></mrow><annotation encoding="application/x-tex">dp[j+2v]=max(dp[j],dp[j+v]-w,dp[j+2v]-2w)+2w;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mpunct">;</span></span></span></span></p><p>…</p><p>这样，每次入队的值是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>j</mi><mo>+</mo><mi>k</mi><mo>∗</mo><mi>v</mi><mo stretchy="false">]</mo><mo>−</mo><mi>k</mi><mo>∗</mo><mi>w</mi></mrow><annotation encoding="application/x-tex">dp[j+k*v]-k*w</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span></span></span></span></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> maxn 110</span></span><br><span class="line"><span class="type">int</span> n, m, v[maxn], w[maxn], s[maxn];</span><br><span class="line"><span class="type">int</span> f[<span class="number">2</span>][maxn];</span><br><span class="line"></span><br><span class="line"><span class="comment">//创建商品的结构体(或者类也可以)</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Goods</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> w, v;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="type">int</span> q[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化数据 </span></span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>, &amp;n, &amp;m);</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d%d&quot;</span>, &amp;v[i], &amp;w[i], &amp;s[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> r = <span class="number">0</span>; r &lt;= v[i]; r++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> hh = <span class="number">0</span>, tt = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> j = r; j &lt;= m; j += v[i])</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">while</span> (hh &lt;= tt &amp;&amp; j - q[hh] &gt; s[i] * v[i])</span><br><span class="line">&#123;</span><br><span class="line">hh++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">while</span> (hh &lt;= tt &amp;&amp; f[(i - <span class="number">1</span>) &amp; <span class="number">1</span>][q[tt]] + (j - q[tt]) / v[i] * w[i] &lt;= f[(i - <span class="number">1</span>) &amp; <span class="number">1</span>][j])</span><br><span class="line">&#123;</span><br><span class="line">tt--;</span><br><span class="line">&#125;</span><br><span class="line">q[++tt] = j;</span><br><span class="line">f[i &amp; <span class="number">1</span>][j] = f[(i - <span class="number">1</span>) * <span class="number">1</span>][q[hh]] + (j - q[hh]) / v[i] * w[i];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">cout &lt;&lt; f[n &amp; <span class="number">1</span>][m] &lt;&lt; endl;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><p><a href="https://www.lanqiao.cn/problems/1176/learning/?page=1&amp;first_category_id=1&amp;problem_id=1176">1.小明的背包3 - 蓝桥云课</a> 这一题就是典型的数据量比较小，可以使用多重背包基础模型实现。</p></li><li><p><a href="https://www.lanqiao.cn/problems/4059/learning/?page=1&amp;first_category_id=1&amp;problem_id=4059">1.新一的宝藏搜寻加强版 - 蓝桥云课</a></p></li></ul><h3 id="二维费用背包-分组背包">二维费用背包&amp;&amp;分组背包</h3><p>【概念】<strong>二维费用背包</strong>：有一个体积为V的背包，商店有n种物品，每种物品有一个价值v、体积w、重量m,每种物品仅有1个，问能够装下物品的最大价值。这里每一种物品只有2种状态即“拿0个、1个”，但是需要同时考虑体积和重量的限制。只需要在01背包的基础上稍加改动，将<strong>状态转移方程修改为二维的即可，同样是倒着更新</strong>。dp[]表示当前体积为i,重量为j的情况下所能拿的物品的最大价值。状态转移方程为<code>dp[i][j]=max(dp[i][j],dp[i-w][j-m]+v);</code></p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/3937/learning/?page=1&amp;first_category_id=1&amp;problem_id=3937">1.小蓝的神秘行囊 - 蓝桥云课</a></li></ul><p>【概念】<strong>分组背包</strong>：有一个体积为V的背包，商店有组物品，每组物品有若干个价值v、体积w,每组物品中至多选1个，问能够装下物品的最大价值。前面已经见过这么多背包了，在这里就直接给出分组背包的定义。设状态<code>dp[i][j]</code>表示到第i组，体积为j的最大价值，在这里<strong>不能忽略第一维，否则可能导致状态转移错误</strong>！状态转移方程为：<code>dp[i][j]=max(dp[i-1][j],dp[i-1][j-w+v);</code></p><ul><li><a href="https://www.lanqiao.cn/problems/1178/learning/?page=1&amp;first_category_id=1&amp;problem_id=1178">1.小明的背包5 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_13">点击此处</a></p><h3 id="完全背包">完全背包</h3><p>【概念】：完全背包也叫无穷背包，即每种物品有无数个的背包。有一个体积为V的背包，商店有个物品，每个物品有一个价值v和体积w,每个物品有无限多个，可以被拿无穷次，问能够装下物品的最大价值。这里每一种物品只有无穷种状态即“拿0个、1个、2个…无穷多个”。设状态dp[i]表示<strong>拿的物品总体积为j的情况下的最大价值</strong>。我们并不关心某个物品拿了儿个，<strong>只关心当前体积下的最大价值</strong>。转移方程为：dp[i]=max(dp[i],dp[i-w]+v),现在就<strong>必须使用“新数据”来更新“新数据”</strong>，因为新数据中包括了拿当前这个物品的状态，而当前这个物品是可以被拿无数次的。最后输出dp[V]即可。</p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/1175/learning/?page=1&amp;first_category_id=1&amp;problem_id=1175">1.小明的背包2 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_13">点击此处</a></p><h3 id="期望DP">期望DP</h3><p>【概念】：这一部分的内容涉及到<strong>期望</strong>，也就是实验中每次可能的结果乘以其结果概率的总和。其相关性质参考概率论与数理统计。对于一些比较难找到递推关系的数学期望问题，可以利用期望的定义式，根据实际情况以概率或者方案数(也就是概率*总方案数)作为一种状态，将问题变成比较一般的统计方案数问题或者利用全概率公式计算概率的递推问题</p><p>【相关数学公式】</p><p>全概率公式:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo stretchy="false">(</mo><mi>B</mi><mo stretchy="false">)</mo><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mi>P</mi><mo stretchy="false">(</mo><msub><mi>A</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mi>P</mi><mo stretchy="false">(</mo><mi>B</mi><mi mathvariant="normal">∣</mi><msub><mi>A</mi><mi>i</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">P(B)=\sum_{i=1}^{n}P(A_i)P(B|A_i)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.104em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> B事件发生的概率=A1事件发生的概率*在A1事件发生的情况下B事件发生的概率+A2……</p><p>一般来说，概率DP找到正确的状态定义后，转移是比较容易想到的。但状态一定是“可数的，把有范围的整数作为数组下标。事实上，将问题直接作为状态是最好的。如问“人做X事的期望次</p><p>【例题】</p><ul><li>给定一副卡片，这幅卡片一共有k种，小明的钱足够买n张卡片，问n张能买到不同卡片的种类数的<strong>期望值</strong></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> maxn 1100000</span></span><br><span class="line"><span class="type">double</span> f[maxn];</span><br><span class="line"><span class="type">int</span> n,k;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>,&amp;n,&amp;k);</span><br><span class="line">f[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"><span class="comment">//其实就是在用动态规划的方法实现期望值的计算 </span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">f[i] = f[i<span class="number">-1</span>]+(k-f[i<span class="number">-1</span>])/k;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%.61f\n&quot;</span>,f[n]);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>给定一副卡片，这幅卡片一共有k种，小明想道买完k种需要买多少张卡片</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="meta">#<span class="keyword">define</span> maxn 1100000</span></span><br><span class="line"><span class="type">double</span> f[maxn];</span><br><span class="line"><span class="type">int</span> n,k;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d&quot;</span>,&amp;n,&amp;k);</span><br><span class="line">f[<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"><span class="comment">//其实就是在用动态规划的方法实现期望值的计算 </span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=k;i++)</span><br><span class="line">&#123;</span><br><span class="line">f[i] = f[i<span class="number">-1</span>]+(<span class="type">double</span>)k/(<span class="type">double</span>)(k-i<span class="number">+1</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%.61f\n&quot;</span>,f[n]);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_14">点击此处</a></p><h3 id="区间DP">区间DP</h3><p>【概念】:可以将一个大区间的问题拆成若干个子区间合并的问题,两个连续的子区间可以进行整合、合并成一个大区间</p><p>【实现】：</p><ol><li>从小到大枚举区间长度。</li><li>对于每一个区间长度，枚举该长度的每一个区间。</li><li>对于每一个区间，枚举所有可能出现的两个子区间的组合。</li><li>对于每一个子区间的组合，计算出合并所需代价。</li><li>求出当前区间的最优值。例如令<code>f[i][j]</code>为区间[l,r]的最大价值，则<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">{</mo><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">]</mo><mi>f</mi><mo stretchy="false">[</mo><mi>k</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo>+</mo><mi>c</mi><mi>o</mi><mi>s</mi><mi>t</mi><mi mathvariant="normal">∣</mi><mi>l</mi><mo>≤</mo><mi>k</mi><mo>&lt;</mo><mi>r</mi><mo stretchy="false">}</mo></mrow><annotation encoding="application/x-tex">f[i][j]=max\{f[i][k]f[k+1][r]+cost|l \leq k&lt;r\}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">]</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">cos</span><span class="mord mathnormal">t</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">}</span></span></span></span></li></ol><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/1233/learning/?page=1&amp;first_category_id=1&amp;sort=difficulty&amp;asc=1&amp;problem_id=1233">1.石子合并 - 蓝桥云课</a></li></ul><p>分析：令<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span></span></span></span>为将区间[i,j]合并为一堆的最小花费，那么可以枚举所有的中间点k将区间[i,j]分成[i,k]和[k+1,j]两部分。那么<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">]</mo><mo>+</mo><mi>f</mi><mo stretchy="false">[</mo><mi>k</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>+</mo><mi>s</mi><mi>u</mi><mi>m</mi><mo stretchy="false">(</mo><mi>i</mi><mo separator="true">,</mo><mi>k</mi><mo stretchy="false">)</mo><mo>+</mo><mi>s</mi><mi>u</mi><mi>m</mi><mo stretchy="false">(</mo><mi>k</mi><mo>+</mo><mn>1</mn><mo separator="true">,</mo><mi>j</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f[i][k]+f[k+1][j]+sum(i,k)+sum(k+1,j)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">m</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">m</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">)</span></span></span></span>就是先将[i,k]合并为一堆，再将[k+1,j]合并为一堆，最后将这两堆合并成[i,j]的最小花费。在所有的[i,k]和[k+1,j]合并中选一个总价值最小的作为合并[i,j]的答案，即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span></span></span></span>。转移方程$f[i][j]=min{f[i][k]+f[k+1][j]+sum(i,j) | i≤k&lt;r} $</p><ul><li><a href="https://www.lanqiao.cn/problems/926/learning/?page=1&amp;first_category_id=1&amp;sort=difficulty&amp;asc=1&amp;problem_id=926">1.涂色 - 蓝桥云课</a></li></ul><p>分析：对于区间[l,r]考虑其端点处的颜色，只有端点颜色相同和不同两种情况。可以枚举k作为分界，将整个区间拆分成[l,k]和[k+1,r]两个区间分别涂色,得到不同情况下的转移方程</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.36em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo stretchy="false">(</mo><mi>l</mi><mo>=</mo><mi>r</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>m</mi><mi>i</mi><mi>n</mi><mo stretchy="false">{</mo><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">}</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo stretchy="false">(</mo><mi>c</mi><mi>o</mi><mi>l</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo>=</mo><mi>c</mi><mi>o</mi><mi>l</mi><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>m</mi><mi>i</mi><mi>n</mi><mo stretchy="false">{</mo><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">]</mo><mo>+</mo><mi>f</mi><mo stretchy="false">[</mo><mi>k</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mi mathvariant="normal">∣</mi><mi>i</mi><mo>≤</mo><mi>k</mi><mo>&lt;</mo><mi>r</mi><mo stretchy="false">}</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo stretchy="false">(</mo><mi>c</mi><mi>o</mi><mi>l</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo mathvariant="normal">≠</mo><mi>c</mi><mi>o</mi><mi>l</mi><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">f[i][j]=\begin{cases} 1 &amp; (l=r) \\ min\{f[l+1][r],f[l][r-1]\} &amp;(col[l]=col[r])\\ min\{f[l][k]+f[k+1][r]| i≤k&lt;r\} &amp; (col[l]\neq col[r]) \end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewbox="0 0 888.89 316" preserveaspectratio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewbox="0 0 888.89 316" preserveaspectratio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">min</span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">]}</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">min</span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mord">∣</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">}</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">)</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">co</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">co</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">])</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mopen">(</span><span class="mord mathnormal">co</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">co</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">])</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><ul><li><a href="https://www.lanqiao.cn/problems/1547/learning/?page=1&amp;first_category_id=1&amp;second_category_id=6&amp;problem_id=1547">1.制作回文串 - 蓝桥云课</a></li></ul><p>如果一个字符串是回文串，那么两边+相同的字符依然是回文串，那么令<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[l][r]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span></span></span></span>为将区间[l,r]变成回文串的最小花费，如果s[l]=s[r],即当前串两端字符相同，那么<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo>=</mo><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[l][r]=f[l+1][r-1]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span></span></span></span></p><p>如果不是的话，可以先将A[…]E这样的通常的字符串拆分成单独的A和[…]E,先将后者修改为回文串，然后考虑删去A或者是在后者+A，最后选择最便宜的操作即可，即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>i</mi><mi>n</mi><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo>+</mo><mi>c</mi><mi>o</mi><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>f</mi><mo stretchy="false">[</mo><mi>l</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>r</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo>+</mo><mi>c</mi><mi>o</mi><mi>s</mi><mi>t</mi><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f[l][r]=min(f[l+1][r]+cost[l],f[l][r -1]+cost[r])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">min</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">cos</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">cos</span><span class="mord mathnormal">t</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">])</span></span></span></span>  得到相应的转移方程，写代码即可</p><p><strong>环形DP</strong>：前面介绍的都是普通DP，而环形DP与普通区间DP的区别只在于环形区间DP的区间是首尾相连的</p><p>【实现】</p><ol><li>数据的处理方法是将原区间复制一份在后边，总长度×2.</li><li>枚举的方法与普通区间DP一致。</li><li>统计答案时要枚举所有的答案区间，找出最优答案。</li></ol><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/557/learning/?page=1&amp;first_category_id=1&amp;second_category_id=6&amp;problem_id=557">1.能量项链 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_14">点击此处</a></p><h3 id="树形DP">树形DP</h3><h4 id="换根DP">换根DP</h4><p>【概念】换根DP：以树上的不同点作为根，其解不同，无法通过一次搜索完成答案的求解，因为一次搜索只能得到一个节点的答案。题目描述大致如：一棵树求以哪一个节点为根的时候，xxx最大/最小。先以树形DP的形式求出以某一个点为根的时候的答案（一般都是以1为根的时候），然后再进行一次自上而下的DFS计算答案。也就是说，分两步，1.树形DP  2.在进行第二次DFS时，两个点之间的关系。</p><p>【例题】:给定一个个点的无根树，问以树上哪个节点为根时，其所有节点的深度和最大？深度：节点到根的简单路径上边的数量 n&lt;=1e5</p><p>如果我们假设某个节点为根，将无根树化为有根树，在搜索回溯时统计子树的深度和，则可以用一次搜索算出以该节点为根时的深<br>度和，其时间复杂度为O(n)如果我们每个点都这么求，则n^2.</p><p>所以我们考虑在第二次搜索时就完成所有节点答案的统计.我们假设第一次搜索时的根节点为1号节点，则此时只有1号节点的答案是已知的。同时第一次搜索可以统计出所有子树的大小。第二次搜索依旧从1号节点出发，若1号节点与节点x相连，则我们考虑能否通过1号节点的答案去推出节点x的答案。我们假设此时将根节点换成节点x,则其子树由两部分构成，第一部分是其原子树，第二部分则是1号节点的其他子树。根从1号节点变为节点x的过程中，我们可以发现第一部分的深度降低了1，第二部分的深度则上升了1，而这两部分节点的数量在第一次搜索时就得到了。即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>n</mi><mi>s</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo>=</mo><mi>a</mi><mi>n</mi><mi>s</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo>−</mo><mi>s</mi><mi>i</mi><mi>z</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo>+</mo><mo stretchy="false">(</mo><mi>s</mi><mi>i</mi><mi>z</mi><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo>−</mo><mi>s</mi><mi>i</mi><mi>z</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">ans[v] =ans[u]-siz[v]+(siz[1]-siz[v])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">an</span><span class="mord mathnormal">s</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">an</span><span class="mord mathnormal">s</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">])</span></span></span></span></p><ul><li>给定一棵个点的无根树，点带权，边带权，求一个点，使得其他点到这个点的距离和最小。其中距离：a-&gt;b的距离为a的点权乘以a-&gt;b的路径长度</li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_14">点击此处</a></p><h4 id="路径相关树形DP">路径相关树形DP</h4><p>【例题引入】:给你一个n(1≤n≤2000)个点的树。给你m(1≤n≤2000)条树上的简单路径，每个路径有个权值<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mi>i</mi></msub><mo stretchy="false">(</mo><mn>1</mn><mo>≤</mo><msub><mi>a</mi><mi>i</mi></msub><mo>≤</mo><msup><mn>10</mn><mn>9</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a_i(1\leq a_i\leq10^9)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>.要求选择一些路径，使得每个点至多在一条路径上，并且路径的权值和最大。</p><p>【实现方案】：</p><p><strong>思路1</strong></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span></span></span></span>表示以i为根节点的子树中，选择了通过节点i的路径j的最大路径权值和。 g[i]表示节点i没向i上面延伸出去的最优解。</p><p>转移方程如下：</p><ol><li>j=0,i不在任何路径中，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo><mo>=</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo></mrow></msub><mtext> </mtext><mi>g</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][0] = \sum_{v\in son[u]}\ g[v]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">u</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span></span></span></span></li><li>j!=0,i在路径j上，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mi>f</mi><mo stretchy="false">[</mo><mo stretchy="false">?</mo><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>−</mo><mi>g</mi><mo stretchy="false">[</mo><mo stretchy="false">?</mo><mo stretchy="false">]</mo><mo>+</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo></mrow></msub><mi>g</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][j] = f[?][j]-g[?]+\sum_{v \in son[u]}g[v]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mclose">?]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">[</span><span class="mclose">?]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">u</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span></span></span></span></li></ol><p><strong>思路2</strong></p><p>f[i]表示节点i没向i上面延伸出去的最优解。</p><p>转移方程如下</p><ol><li>i不在任何路径中，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>=</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo></mrow></msub><mtext> </mtext><mi>f</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i] = \sum_{v\in son[u]}\ f[v]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">u</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span></span></span></span></li><li>考虑i在路径j上且为最高点，考虑将路径j删去，把剩下的若干个子树的f值求和再加上该路径的权值即可</li></ol><p>实现代码如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll;</span><br><span class="line"><span class="type">int</span> n, m;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1000</span>;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt;e[N], t;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">asdf</span></span><br><span class="line">&#123;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; vec;</span><br><span class="line">ll val;</span><br><span class="line">&#125;;</span><br><span class="line">vector&lt;asdf&gt;w[N];</span><br><span class="line">ll dp[N];</span><br><span class="line"><span class="type">int</span> n, m, k, dep[N] = &#123; <span class="number">1</span> &#125;, f[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> u)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">auto</span> v : e[u])</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">dfs</span>(v);</span><br><span class="line">dp[u] += dp[v];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">auto</span> t : w[u])</span><br><span class="line">&#123;</span><br><span class="line">ll sum = dp[u];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">auto</span> nw : t.vec)</span><br><span class="line">&#123;</span><br><span class="line">sum -= dp[nw];</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">auto</span> v : e[nw])</span><br><span class="line">&#123;</span><br><span class="line">sum += dp[v];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">dp[u] = <span class="built_in">max</span>(dp[u], sum + t.val);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>), cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line">cin &gt;&gt; n &gt;&gt; m;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">2</span>; i &lt;= n; i++)</span><br><span class="line">&#123;</span><br><span class="line">cin &gt;&gt; f[<span class="number">1</span>];</span><br><span class="line">e[f[i]].<span class="built_in">push_back</span>(i);</span><br><span class="line">dep[i] = dep[f[i]] + <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">1</span>, x, y; i &lt;= m; i++)</span><br><span class="line">&#123;</span><br><span class="line">ll val;</span><br><span class="line">cin &gt;&gt; x &gt;&gt; y &gt;&gt; val;</span><br><span class="line">t.<span class="built_in">clear</span>();</span><br><span class="line"><span class="keyword">while</span> (x != y)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (dep[x] &gt; dep[y])</span><br><span class="line">&#123;</span><br><span class="line">t.<span class="built_in">push_back</span>(x);</span><br><span class="line">x = f[x];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">t.<span class="built_in">push_back</span>(y);</span><br><span class="line">y = f[y];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">t.<span class="built_in">push_back</span>(x);</span><br><span class="line">w[x].<span class="built_in">push_back</span>(&#123; t,val &#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">dfs</span>(<span class="number">1</span>);</span><br><span class="line">cout &lt;&lt; dp[<span class="number">1</span>];</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题引入】：给你一个(1≤n≤2000)个点的树。给你m(1≤m≤2000)条树上的简单路径，每个路径有个权值<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mi>i</mi></msub><mo stretchy="false">(</mo><mn>1</mn><mo>≤</mo><msub><mi>a</mi><mi>i</mi></msub><mo>≤</mo><msup><mn>10</mn><mn>9</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">a_i(1\leq a_i\leq10^9)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">9</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>.。这里保证每条路径都是从一个点到它的祖先(也就是<strong>根节点)</strong>。要求选择一些路径，使得每个点至少在一条路径上，并且路径的权值和最小。如果不存在，输出-1。</p><p>分析：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[i][j]]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]]</span></span></span></span>以节点i为根的子树中全部被覆盖，且往根最高延伸到深度j的节点的最小代价。相当于每条路径在最低点考虑。其转移方程为</p><ol><li>假设不选择以i为最低点的路径，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo></mrow></msub><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>d</mi><mi>e</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo>+</mo><mi>m</mi><mi>i</mi><msub><mi>n</mi><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo></mrow></msub><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>−</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>d</mi><mi>e</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">dp[i][j] = \sum_{v \in son[i]}dp[v][dep[i]+1]+min_{v \in son[i]}(dp[v][j]-dp[v][dep[i]+1])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1052em;vertical-align:-0.3552em;"></span><span class="mord mathnormal">mi</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">])</span></span></span></span></li><li>对于每一条以i为最低点的路径v，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>d</mi><mi>e</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mi mathvariant="normal">.</mi><mi>x</mi><mo stretchy="false">]</mo><mo>=</mo><mi>m</mi><mi>i</mi><mi>n</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>d</mi><mi>e</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mi mathvariant="normal">.</mi><mi>x</mi><mo stretchy="false">]</mo><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>v</mi><mi mathvariant="normal">.</mi><mi>v</mi><mi>a</mi><mi>l</mi><mo>+</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo></mrow></msub><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>d</mi><mi>e</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>+</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">dp[i][dep[v.x] = min(dp[i][dep[v.x]],v.val+\sum_{v \in son[i]}dp[v][dep[i]+1])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord">.</span><span class="mord mathnormal">x</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">min</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord">.</span><span class="mord mathnormal">x</span><span class="mclose">]]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord">.</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">i</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">])</span></span></span></span></li></ol><h4 id="自下而上的树形DP">自下而上的树形DP</h4><p>【例题引入】：给一颗有根树，每个点都有一个权值i,要选择一些点使得权值利最大，且一个点若被选择，其儿子不能被选择，问最大值。其中(<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo><mi>n</mi><mo>≤</mo><msup><mn>10</mn><mn>5</mn></msup><mo separator="true">,</mo><mn>1</mn><mo>≤</mo><msub><mi>a</mi><mi>i</mi></msub><mo>≤</mo><msup><mn>10</mn><mn>6</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">1\leq n\leq10^5,1\leq a_i \leq 10^6)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></p><p>这类题目通常树形dp状态设定，用一维表示当前子树，但这里题目要求儿子结点和自己不能同时选择，因此对于每个结点，选不选择影响着儿子节点，所以多开一维记录选没选。分类处理一下即可。形式化一点来讲，设<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][0]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span></span></span></span>表示当前点不选的最大值,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[i][1]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">]</span></span></span></span>表示当前点选了的最大值。</p><p>【例题】</p><ul><li>给一棵树和背包体积v,每个点有一个权值wi,和体积vi,要求选些点权值最大，且体积和不超过背包容量，一个点被选，儿子不能选，求最大值。其中<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo><mi>n</mi><mo>≤</mo><mn>100</mn><mo separator="true">,</mo><mn>1</mn><mo>≤</mo><mi>v</mi><mo>≤</mo><mn>100</mn><mo separator="true">,</mo><mn>1</mn><mo>≤</mo><msub><mi>w</mi><mi>i</mi></msub><mo separator="true">,</mo><msub><mi>v</mi><mi>i</mi></msub><mo>≤</mo><mn>100</mn></mrow><annotation encoding="application/x-tex">1 \leq n \leq 100,1 \leq v \leq 100,1\leq w_i,v_i \leq 100</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">100</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">100</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">100</span></span></span></span></li></ul><p>设<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">f[u][v]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span></span></span></span>表示u这颗子树用了v体积且选了u这个点的最大价值。枚举子树，进行合并转移即可</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_15">点击此处</a></p><h4 id="自下而上的树形DP-v2">自下而上的树形DP</h4><p>【例题引入】：<strong>最大独立集问题</strong> 蓝桥公司一共有n名员工，编号分别为1~n。他们之间的关系就像一棵以董事长为根的树，父节点就是子节点的直接上司。每个员工有一个快乐指数ai.现蓝桥董事会决定举办一场蓝桥舞会来让员工们在工作之余享受美好时光，不过对于每个员工，他们都不愿意与自己的直接上司一起参会。董事会希望舞会的所有参会员工的快乐指数总和最大，请你求出这个最大值。其中<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo><mi>u</mi><mo separator="true">,</mo><mi>v</mi><mo separator="true">,</mo><msub><mi>a</mi><mi>i</mi></msub><mo>≤</mo><mi>n</mi><mo>≤</mo><msup><mn>10</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">1 \leq u,v,a_i \leq n \leq 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">u</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span></p><p>分析：选择若干个点，使得没有相邻的两个点均被选择。最大化被选择的点的点权和。</p><p>其状态为：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[u][0]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span></span></span></span>表示在以u为根节点的子树中选择两两不相邻的若干个点，不选点u的最大权值和。<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[u][1]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">]</span></span></span></span>表示在以u为根节点的子树中选择两两不相邻的若干个点，选了点u的最大权值和。</p><p>转移方程为</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo><mo>=</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo></mrow></msub><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">dp[u][0] =\sum_{v \in son[u]}max(dp[v][0],dp[v][1])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">u</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">])</span></span></span></span>;<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo>=</mo><mi>v</mi><mi>a</mi><mi>l</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo><mo>+</mo><msub><mo>∑</mo><mrow><mi>v</mi><mo>∈</mo><mi>s</mi><mi>o</mi><mi>n</mi><mo stretchy="false">[</mo><mi>u</mi><mo stretchy="false">]</mo></mrow></msub><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>v</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[u][1] = val[u]+ \sum_{v \in son[u]} dp[v][0]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mopen">[</span><span class="mord mathnormal">u</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight">n</span><span class="mopen mtight">[</span><span class="mord mathnormal mtight">u</span><span class="mclose mtight">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span></span></span></span>;</p><p>最终得到的答案为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>a</mi><mi>n</mi><mi>s</mi><mo>=</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>r</mi><mi>o</mi><mi>o</mi><mi>t</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>0</mn><mo stretchy="false">]</mo><mo separator="true">,</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>r</mi><mi>o</mi><mi>o</mi><mi>t</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">ans = max(dp[root][0],dp[root][1])</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">an</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">roo</span><span class="mord mathnormal">t</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">0</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">roo</span><span class="mord mathnormal">t</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord">1</span><span class="mclose">])</span></span></span></span></p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1319/learning/?page=1&amp;first_category_id=1&amp;problem_id=1319">1.蓝桥舞会 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_15">点击此处</a></p><h3 id="数位DP">数位DP</h3><p>【概念】：数位DP往往都是这样的题型，给定一个闭区间[l,r]，让你求这个区间中满足某种条件的数的总数。所谓数位dp.就是对数位讲行dp.也就是个位、十位等</p><p>【实现】</p><p>最常用的枚举方式是控制上界枚举，即控制上界枚举就是要让正在枚举的这个数不能超过上界，我们常常利用一个bool变量limit来表明该数位前的其他数位是否恰好都处于最大状态。如果目前这个数不是这个位置最大的数字，那么可取的范围为0-9，否则范围将被限制在该数位在上界中的最大值。(注意，前导零要根据题目特殊处理)</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/836/learning/?page=1&amp;first_category_id=1&amp;name=windy">1.windy 数 - 蓝桥云课</a></li></ul><p>数位dp解决不用记忆化搜索这个题是在一个区间里找个数所以我们考虑用前缀和的思想只需找出1~m,1n各自的个数再相减就行了<br>设<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">dp[i][j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span></span></span></span>为长度为i中最高位是j的windy数的个数方程<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>=</mo><mi>s</mi><mi>u</mi><mi>m</mi><mo stretchy="false">(</mo><mi>d</mi><mi>p</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo stretchy="false">[</mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">dp[i][j]=sum(dp[i-1][k)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">m</span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mord mathnormal">p</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">)</span></span></span></span>其中abs(j-k)&gt;=2,枚举数位并转移即可。</p><p>其他待后续补充</p><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_15">点击此处</a></p><h3 id="状压DP">状压DP</h3><p>【概念】状态压缩：状态压缩就是使用某种方法来表示某种状态，通常是用一串01数字（二进制数）来表示各个状态。这就要求使用状态压缩的对象的状态必须只有两种，0或1(之前的二进制优化就是使用了此思想)；当然如果有三种状态用三进制来表示也未尝不可。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/186/learning/?page=1&amp;first_category_id=1&amp;name=%E7%B3%96%E6%9E%9C">1.糖果 - 蓝桥云课</a></li></ul><p>像这种题目中要求保留状态的就要考虑状压dp优化，定义状态<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>p</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">dp_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>:为得到组合i的最少糖果包数，即答案为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>p</mi><mrow><mo stretchy="false">(</mo><mn>1</mn><mo>&lt;</mo><mo>&lt;</mo><mi>m</mi><mo stretchy="false">)</mo><mo>−</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">dp_{(1&lt;&lt;m)-1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0496em;vertical-align:-0.3552em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mtight">1</span><span class="mrel mtight">&lt;&lt;</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">)</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span></span>,往组合i中加入一包糖果，得到新的组合j,则从i到j需要包数<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>p</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">dp_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>+1。若原来的<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>p</mi><mi>j</mi></msub></mrow><annotation encoding="application/x-tex">dp_j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9805em;vertical-align:-0.2861em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>,本来就大于<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>p</mi><mi>i</mi></msub><mo>+</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">dp_i+1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>,说明找到了更优解法，更新<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi><msub><mi>p</mi><mi>j</mi></msub></mrow><annotation encoding="application/x-tex">dp_j</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9805em;vertical-align:-0.2861em;"></span><span class="mord mathnormal">d</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>即可。</p><ul><li><a href="https://www.lanqiao.cn/problems/356/learning/?page=1&amp;first_category_id=1&amp;name=%E6%84%A4%E6%80%92%E7%9A%84%E5%B0%8F%E9%B8%9F">1.愤怒的小鸟 - 蓝桥云课</a></li></ul><p>本部分算法实现与例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_16">点击此处</a></p><h2 id="参考">参考</h2><ol><li><a href="https://leetcode.cn/circle/discuss/E3yavq/">力扣刷题攻略</a>  读者可以在这里参考刷题。</li><li>蓝桥云课C++班，作者谢子杨</li></ol>]]></content>
    
    
    <summary type="html">总结了C/C++赛道蓝桥杯常见的题型以及背后的算法原理,为读者提供一个刷题和总结的参考。</summary>
    
    
    
    <category term="algorithm" scheme="https://lloydkai.cn/categories/algorithm/"/>
    
    
    <category term="C" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>算法系列(二)蓝桥杯_算法基础</title>
    <link href="https://lloydkai.cn/posts/lanqiaocup-series-two/"/>
    <id>https://lloydkai.cn/posts/lanqiaocup-series-two/</id>
    <published>2025-01-12T05:31:17.000Z</published>
    <updated>2026-04-23T01:44:52.708Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/rVx9ogHB31wf4mJ.jpg" alt></p><h1>算法基础</h1><blockquote><p>一放假就有点放纵自我了，<strong>不能再堕落下去了，一定要出重拳</strong>！o(<em>￣▽￣</em>)o</p><p>目前以视频的方法为主，等蓝桥杯考完之后按照labuladong或者是考研的方法写代码。</p></blockquote><h2 id="我的仓库使用指南">我的仓库使用指南</h2><p>我的仓库链接格式如下：<code>https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/1_20</code> 其中1_20表示的是日期(一般是2025)，里面的文件就包含对应题目的解答(均通过对应题目的测试)或者是算法实现，其中文件名<code>lanqiao</code>表示 是<strong>蓝桥杯官网上的题目</strong>，<code>_</code> 后面的数字是蓝桥杯的<strong>题目编号</strong>，可以找到对应的蓝桥杯的题目，比如题目链接是<code>https://www.lanqiao.cn/problems/498/learning/?page=1&amp;first_category_id=1&amp;problem_id=498</code>    <code>problems</code>斜杠后面的数字<strong>498</strong> 就是对应的题目编号，你就在我指定链接下面的文件夹下按照<code>lanqiao_题目编号.cpp</code> 这样的格式找对应文件，就可以看到对应题目的解答代码。</p><p><img src="https://s2.loli.net/2025/02/06/n4dH1aOXoCc35Sy.png" alt="001_demo.png"></p><hr><h2 id="差分数组">差分数组</h2><p>【概念】：<code>diff[i] = a[i]-a[i-1];//对于数组a，diff为差分数组  当i=1时，diff[1]=a[1]</code><br>【性质】：对差分数组作前缀和可以将其转化为原数组。 公式：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mi>d</mi><mi>i</mi><mi>f</mi><mi>f</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>=</mo><mi>a</mi><mo stretchy="false">[</mo><mi>n</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">\sum_{i=1}^{n}diff[i]=a[n]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.104em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.10764em;">ff</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mopen">[</span><span class="mord mathnormal">n</span><span class="mclose">]</span></span></span></span></p><p>利用差分数组可以实现快速的区间修改，下面是将区间[l,r]都加上X的方法：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">diff[l]+=x;//相当于a[l]-a[l-1] = x+原来的diff[l];</span><br><span class="line">diff[r+1]-=x;//相当于a[r]-a[r-1] = 原来的diff[r+1]-x;</span><br></pre></td></tr></table></figure><p>在修改完成后，需要<strong>做前缀和恢复为原数组</strong>，所以上面这段代码的含义是：diff[l]+=X表示将区间[l,n]都加上x,但是[r+1,n]我们并不想加x,所以再将[r+1,n]减去x即可。</p><p>这是怎么实现的呢？其实很简单，在通过前缀和恢复为原数组的时候，在区间的起始处+X，用公式计算在区间后面的数一定会加上这个值,比如a[l+1] = diff[1]+diff[2]+……+<strong>diff[l]</strong>+diff[l+1];而这里的diff[l]已经加上X了，<strong>这就是奥妙所在</strong>，而要想只加到r区间，那么同理就是在这个区间的后一个元素减去X(<strong>这里的区间是左右闭合</strong>)，比如a[r+2] = diff[1]+diff[2]+……+<strong>diff[l]</strong>+……+diff[r]+<strong>diff[r+1]</strong>+diff[r+2];这里的diff[l]与diff[r+1]<strong>一加一减X正好抵消</strong>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">diff[i] = a[i]-a[i<span class="number">-1</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><p><a href="https://www.lanqiao.cn/problems/3291/learning/?page=1&amp;first_category_id=1&amp;second_category_id=6&amp;problem_id=3291">1.区间更新 - 蓝桥云课</a>  难点：一是对于差分数组和前缀和性质的掌握，另一个是细节部分，比如对于数组的大小建议使用常数，cin获取输入作为while的判断条件，还有特定条件下输出空格或者是换行符。</p></li><li><p><a href="https://www.lanqiao.cn/problems/1276/learning/?page=1&amp;first_category_id=1&amp;problem_id=1276">1.小明的彩灯 - 蓝桥云课</a>  如果不注意到数组越界和栈溢出的问题很容易无法通过测验。</p></li></ul><p>【实践易错点】</p><p>在 <code>int main</code> 中，声明数组 <code>int arr[N+1]</code> 和 <code>int diff[N+1]</code> 可能会遇到的问题是由于栈内存的限制。栈内存的大小通常有限（在一些编译环境中，栈空间的大小是 1MB 左右）。如果在 <code>main</code> 函数内声明非常大的数组，可能会导致栈溢出错误。我在实际做题的时候就因为这个原因导致无法通过测验，也就提醒<u><strong>读者在初始化数组等不确定大小的数据结构时，尽可能将其在全局区域或者是堆区中事先初始化，以免出现栈溢出、数组越界等问题</strong></u>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span><span class="number">+9</span>;</span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> arr[N];</span><br><span class="line"><span class="type">int</span> diff[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">solve</span><span class="params">(<span class="type">int</span> size,<span class="type">int</span> oper)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//初始化数组与差分数组</span></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=size;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    cin&gt;&gt;arr[i];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=size;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    diff[i] = arr[i]-arr[i<span class="number">-1</span>];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="type">int</span> x = <span class="number">0</span>;</span><br><span class="line">  <span class="type">int</span> y = <span class="number">0</span>;</span><br><span class="line">  <span class="type">int</span> z = <span class="number">0</span>;</span><br><span class="line">  <span class="comment">//区间的操作</span></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;oper;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    cin&gt;&gt;x&gt;&gt;y&gt;&gt;z;</span><br><span class="line">    diff[x]+=z;</span><br><span class="line">    diff[y<span class="number">+1</span>]-=z;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//区间的还原</span></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=size;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    arr[i] = arr[i<span class="number">-1</span>]+diff[i];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//输出数组元素</span></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=size;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;arr[i]&lt;&lt;<span class="string">&quot; \n&quot;</span>[i == size];</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line">  <span class="type">int</span> size = <span class="number">0</span>;</span><br><span class="line">  <span class="type">int</span> oper = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">while</span>(cin&gt;&gt;size&gt;&gt;oper)</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="built_in">solve</span>(size,oper);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><h2 id="递归">递归</h2><p>相关知识点在算法系列(一)中讲解了，这里主要讲做题。<br>【例题】：输入n，求F(n)(F为斐波那契)，其中n&lt;=100000,结果对1e9+7(也就是1*10<sup>9</sup> +7)取模</p><p>示例代码</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">pragma</span> once</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll;</span><br><span class="line"><span class="comment">//定义全局变量</span></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span><span class="number">+9</span>;</span><br><span class="line"><span class="type">const</span> ll p = <span class="number">1e9</span><span class="number">+7</span>;<span class="comment">//在许多题目中经常出现1e9+7，这是在提醒此数超出了int的表示范围，需要使用更大表示范围的数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//带备忘录的递归，能保存以前的计算过的数,提高一定的效率</span></span><br><span class="line">ll dp[N];</span><br><span class="line"></span><br><span class="line"><span class="function">ll <span class="title">fib</span><span class="params">(<span class="type">int</span> n)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(dp[n])<span class="comment">//如果以前记录过此斐波那契数就直接输出 </span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> dp[n];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(n&lt;=<span class="number">2</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;<span class="comment">//递归边界 </span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> dp[n] = (<span class="built_in">fib</span>(n<span class="number">-1</span>)+<span class="built_in">fib</span>(n<span class="number">-2</span>))%p;<span class="comment">//分解为子问题 </span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_fib</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;<span class="built_in">fib</span>(i)&lt;&lt;endl;<span class="comment">//如果要充分发挥备忘录的作用，可以用迭代的方式求出从3到n的所有fib值 </span></span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/760/learning/?page=1&amp;first_category_id=1&amp;problem_id=760">1.数的计算 - 蓝桥云课</a></li></ul><p><strong>分析</strong>：正向看是(6)(1 6)(2 6)(1 2 6)(3 6)(1 3 6),但是从右往左看就是以6开头，其”分支“都是比其”根节点“的一半要小或者相等，这就容易想到使用dfs+递归的方式解决问题。当然只递归也可以实现。示例见<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/1_20">此链接</a>  。</p><h2 id="二分">二分</h2><p>【概念】：是一种高效的查找方法，通过逐次将搜索范围一分为二，快速找到要查找的内容，适用于<strong>有序数据集合</strong>(这里的有序可以是正逆序，等差等比等以一定规律排序的方法)</p><p>常见的二分类型：整数二分，浮点二分，二分答案(<strong>最为常见</strong>)</p><p>【解题步骤】</p><ol><li>研究并发现数据结构（或答案变量）的单调性。</li><li>确定最大区间[l,r]，确保分界点一定在里面，具体有一些细节：若以r作为答案，那么答区间在[l+1,r],若以l作为答案，那么答案区间在[l,r-1]。</li><li><strong>确定check函数</strong>，一般为传入mid（区间中某个下标），返回mid所属区域或返回一个值，当check函数较简单时可以直接判断</li><li><strong>计算中点mid</strong>=(l+r)/2,用check判断该移动l或r指针，具体移动哪个需要根据单调性以及要求的答案来判断。</li><li>返回l或r,根据题意判断。</li></ol><p>【示例】</p><p>对于数组<code>int a = [2,4,4,6,6,10,18];</code> 找第一个&gt;=6的数，就是6的左边界，那么就要返回right。同理，如果要找的是右边界，那么就返回left</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//找到升序数组a中x第一次出现的位置</span></span><br><span class="line"><span class="type">int</span> l=<span class="number">0</span>,r=<span class="number">1e9</span>;</span><br><span class="line"><span class="comment">//注意这里的判断条件，这样可以保证1,r最终一定收敛到分界点</span></span><br><span class="line"><span class="built_in">whi1e</span>(<span class="number">1</span><span class="number">+1</span>!=r)<span class="comment">//即l与r相邻后退出</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> mid = (l+r)/<span class="number">2</span>;</span><br><span class="line"><span class="comment">//如果a为升序，说明mid偏大了，需要减小mid,就只能将r变小，</span></span><br><span class="line"><span class="keyword">if</span>(a[mid]&gt;=x) r = mid;</span><br><span class="line"><span class="keyword">else</span> l = mid;</span><br><span class="line">&#125;</span><br><span class="line">cout &lt;&lt;r &lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br></pre></td></tr></table></figure><p>浮点二分：不再是在有序数组上做二分查找，而是在某个实数范围内进行查找，因为实数域本身是单调的，所以也满足单调性，和整数二分的主要区别在于使用的变量类型、退出的判断条件不同。这个知识点考的比较少，在工科数学中用到较多</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//计算单调函数f(x)的零点</span></span><br><span class="line"><span class="type">double</span> l = <span class="number">0</span>,r = <span class="number">1e9</span>,eps = <span class="number">1e-6</span>;</span><br><span class="line"><span class="comment">//注意这里的判断条件，这样可以保证1,r最终一定收敛到分界点</span></span><br><span class="line"><span class="built_in">whi1e</span>(r-l&gt;=eps)<span class="comment">//eps是一个极小量，设置为1e-6比较合适</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="type">double</span> mid = (l+r)/<span class="number">2</span>;</span><br><span class="line"><span class="comment">//fx单调递增，说明mid偏大了，需要减小mid,就只能将r变小，r = mid</span></span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">f</span>(mid)&gt;=<span class="number">0</span>) r = mid;</span><br><span class="line"><span class="keyword">else</span> l = mid;</span><br><span class="line">&#125;</span><br><span class="line">cout &lt;&lt;r &lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br></pre></td></tr></table></figure><blockquote><p>在考试中的二分题很多时候看起来不是简单的有序序列或者是函数，需要读者自行从题目中分析其二分的本质</p></blockquote><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/1389/learning/?page=1&amp;first_category_id=1&amp;problem_id=1389">1.二分查找数组元素 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/364/learning/?page=1&amp;first_category_id=1&amp;problem_id=364">1.跳石头 - 蓝桥云课</a></li></ul><p>这题就相当具有代表性，直接看这题好像和二分一点关系都没有，但是分析可得发现当“最短跳跃距离”越长时，需要移走的石头数量也越多。于是就产生了单调性，我们通过二分“最短跳跃距离”，在已知“最短跳跃距离”的情况下容易O)计算需要搬走的石头的数量，找到分界点即可（即在至多搬走M块石头的情况下的最远跳跃距离）</p><ul><li><a href="https://www.lanqiao.cn/problems/3683/learning/?page=1&amp;first_category_id=1&amp;problem_id=3683">1.肖恩的苹果林 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/3404/learning/?page=1&amp;first_category_id=1&amp;problem_id=3404">1.肖恩的乘法表 - 蓝桥云课</a></li></ul><p>在某种意义上二分和枚举是一样的思想，就是先确定所有可能值的范围，然后在里面通过一定的方法去缩小答案的范围。</p><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/blob/main/1_21">点击此处</a></p><hr><h2 id="构造">构造</h2><p>【概念】：构造题在比赛和解决问题的过程中确实是常见的一类题型。它们通常要求解题者通过观察问题的结构和规律，找到一种通用的方法或模式，使得在问题规模增大时依然能够高效地得到答案。其思想就是数学中的<strong>构造函数</strong>、<strong>找规律</strong>。</p><p>这一部分主要<strong>侧重于读者的理解和归纳能力</strong>，由于构造方法多样且因人而异，关于其概念和方法讲解不会太多，而侧重于讲解例题加深读者对构造的理解。</p><p>【例题1】</p><blockquote><p>蓝桥小蓝喜欢数学，他特别喜欢做数学题，有一天他遇到了一个有趣的数学题：<br><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mn>1</mn><mi>x</mi></mfrac><mo>+</mo><mfrac><mn>1</mn><mi>y</mi></mfrac><mo>+</mo><mfrac><mn>1</mn><mi>z</mi></mfrac><mo>=</mo><mfrac><mn>1</mn><mi>N</mi></mfrac></mrow><annotation encoding="application/x-tex">\frac{1}{x}+\frac{1}{y}+\frac{1}{z}=\frac{1}{N}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.3262em;vertical-align:-0.4811em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4811em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><br>现在给定一个正整数N,小蓝想知道当x、y、z取何值时，上述等式成立。<br>请你帮助小蓝找到满足条件的整数x、y、z.<br>输入：输入包含一个正整数N(1≤N≤1000).<br>输出：如果存在满足条件的整数x、y、z,则输出一个满足条件的解，以空格分隔。如果有多组解，请输出任意一组即可。<br>如果不存在满足条件的解，则输出&quot;No Solution&quot;。</p></blockquote><p>给出的样例如下：</p><blockquote><p>样例1:<br>输入：<br>N=1<br>输出：<br>2 3 6<br>样例2:<br>输入：<br>N=2<br>输出：<br>4 6 12<br>样例3:<br>输入：<br>N=3<br>输出：<br>7 10 70</p></blockquote><p>看起来好像第三项是第二项的两倍，但是当N=3的时候又不是这样，难道规律不对？其实题目中告诉你只需要找任意一个解，但出题人可不会把有规律的直接告诉你，而这个时候我们需要用<strong>数学推导</strong>以下<strong>验证我们的猜想</strong>.</p><p>当N=2时,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>=</mo><mfrac><mn>1</mn><mn>4</mn></mfrac><mo>+</mo><mfrac><mn>1</mn><mn>4</mn></mfrac><mo separator="true">,</mo><mfrac><mn>1</mn><mn>4</mn></mfrac><mo>=</mo><mfrac><mn>3</mn><mn>12</mn></mfrac><mo>=</mo><mfrac><mn>1</mn><mn>12</mn></mfrac><mo>+</mo><mfrac><mn>2</mn><mn>12</mn></mfrac><mo>=</mo><mfrac><mn>1</mn><mn>12</mn></mfrac><mo>+</mo><mfrac><mn>1</mn><mn>6</mn></mfrac></mrow><annotation encoding="application/x-tex">\frac{1}{2}=\frac{1}{4}+\frac{1}{4},\frac{1}{4}=\frac{3}{12}=\frac{1}{12}+\frac{2}{12}=\frac{1}{12}+\frac{1}{6}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">3</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">6</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>,推导可得，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mn>1</mn><mn>2</mn></mfrac><mo>=</mo><mfrac><mn>1</mn><mn>4</mn></mfrac><mo>+</mo><mfrac><mn>1</mn><mn>6</mn></mfrac><mo>+</mo><mfrac><mn>1</mn><mn>12</mn></mfrac></mrow><annotation encoding="application/x-tex">\frac{1}{2} = \frac{1}{4}+\frac{1}{6}+\frac{1}{12}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">6</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> x= 4,y= 6,z=12</p><p>当N=3时同理可得，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mn>1</mn><mn>3</mn></mfrac><mo>=</mo><mfrac><mn>1</mn><mn>6</mn></mfrac><mo>+</mo><mfrac><mn>1</mn><mn>9</mn></mfrac><mo>+</mo><mfrac><mn>1</mn><mn>18</mn></mfrac></mrow><annotation encoding="application/x-tex">\frac{1}{3} = \frac{1}{6}+\frac{1}{9}+\frac{1}{18}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">3</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">6</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">9</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">18</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> x=6,y=9,z=18 看到没有，出题老登果然出一些偏数据误导你，但是只要你按照数学思维推导，还是能找到一定的规律的.</p><p>由数学归纳法得，当N = n时 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mfrac><mn>1</mn><mi>n</mi></mfrac><mo>=</mo><mfrac><mn>1</mn><mrow><mn>2</mn><mi>n</mi></mrow></mfrac><mo>+</mo><mfrac><mn>1</mn><mrow><mn>3</mn><mi>n</mi></mrow></mfrac><mo>+</mo><mfrac><mn>1</mn><mrow><mn>6</mn><mi>n</mi></mrow></mfrac></mrow><annotation encoding="application/x-tex">\frac{1}{n} = \frac{1}{2n}+\frac{1}{3n}+\frac{1}{6n}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">3</span><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">6</span><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> 即x=2n,y=3n,z=6n 证明完毕，剩下的就是将数学语言转化为计算机语言了。</p><hr><blockquote><p>总结：这类题目出题千变万化，没有通解，需要读者不断观察、猜想、证明、修正，直到找到相对准确的规律或者是构造方法。</p></blockquote><hr><h2 id="进制转换">进制转换</h2><p>【概念】：每一个数位上的数字*这一位的权重(也就是<strong>进制</strong>)。</p><p>【示例】：十进制：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>153</mn><mo>=</mo><mo stretchy="false">(</mo><mn>1</mn><mo>×</mo><msup><mn>10</mn><mn>2</mn></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mn>5</mn><mo>×</mo><msup><mn>10</mn><mn>1</mn></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mn>3</mn><mo>×</mo><msup><mn>10</mn><mn>0</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">153 = (1\times10^2)+(5\times10^1)+(3\times10^0)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">153</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">5</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>  二进制：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mn>5</mn><msub><mo stretchy="false">)</mo><mn>10</mn></msub><mo>=</mo><mo stretchy="false">(</mo><mn>1</mn><mo>×</mo><msup><mn>2</mn><mn>2</mn></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mn>0</mn><mo>×</mo><msup><mn>2</mn><mn>1</mn></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><mn>1</mn><mo>×</mo><msup><mn>2</mn><mn>0</mn></msup><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mn>101</mn><msub><mo stretchy="false">)</mo><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">(5)_{10} = (1\times2^2)+(0\times2^1)+(1\times2^0)=(101)_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">5</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">10</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">101</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></p><h3 id="常见考点">常见考点</h3><ol><li>将任意进制转化为十进制</li></ol><p>【思路】：从高位到低位获取每一位的数字并乘以权重+每一位的数字</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">long</span> <span class="type">long</span> x = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">x = x*k+a[i];</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;x&lt;&lt;endl;</span><br></pre></td></tr></table></figure><p>数学推导</p><blockquote><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>=</mo><mn>1</mn><mo separator="true">,</mo><mi>x</mi><mo>=</mo><mn>1</mn><mo>×</mo><msup><mi>k</mi><mn>0</mn></msup></mrow><annotation encoding="application/x-tex">i = 1,x = 1 \times k^0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi><mo>=</mo><mn>2</mn><mo separator="true">,</mo><mi>x</mi><mo>=</mo><mn>1</mn><mo>×</mo><msup><mi>k</mi><mn>1</mn></msup><mo>+</mo><mn>3</mn><mo>×</mo><msup><mi>k</mi><mn>0</mn></msup></mrow><annotation encoding="application/x-tex">i = 2,x = 1 \times k^1+3 \times k^0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span></span></span></span></p><p>……</p><p>就是从高位开始，不断×权重+对应位的数字。<br>这个k进制的数组可以通过对<strong>输入字符串的处理</strong>得到，而且考题大多都是这样。</p></blockquote><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/2489/learning/?page=1&amp;first_category_id=1&amp;problem_id=2489">1.进制 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/2095/learning/?page=1&amp;first_category_id=1&amp;problem_id=2095">1.九进制转十进制 - 蓝桥云课</a> 实现思路同上一题，仓库中就不展示其解答代码</li></ul><ol start="2"><li>将十进制转为任意进制</li></ol><p>【思路】：由定义可得<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>=</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mi>n</mi></msub><mo>×</mo><msup><mi>k</mi><mi>n</mi></msup><mo stretchy="false">)</mo><mo>+</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>+</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mn>1</mn></msub><mo>×</mo><msup><mi>k</mi><mn>1</mn></msup><mo stretchy="false">)</mo><mo>+</mo><mo stretchy="false">(</mo><msub><mi>a</mi><mn>0</mn></msub><mo>×</mo><msup><mi>k</mi><mn>0</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x = (a_n\times k^n)+...+(a_1\times k^1)+(a_0\times k^0)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">...</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 可以直接计算出<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">a_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>=x%k 。计算出来之后呢？将x/=k，然后将<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">a_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>放在<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>a</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">a_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>的位置上，继续执行此操作即可</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">ll x;</span><br><span class="line">cin &gt;&gt; x;</span><br><span class="line">ll a[n];<span class="comment">//自己定义其大小</span></span><br><span class="line"><span class="keyword">while</span>(x)</span><br><span class="line">&#123;</span><br><span class="line">a[++ cnt] = x%k,x/=k;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">reverse</span>(a<span class="number">+1</span>,a<span class="number">+1</span>+cnt);<span class="comment">//注意要翻转，才能使得高位在1的位置</span></span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1230/learning/?page=1&amp;first_category_id=1&amp;problem_id=1230">1.进制转换 - 蓝桥云课</a> 对于N进制转M进制，一个好的方法就是先将N转化为十进制，然后将十进制转化为M进制。这里就用到算法系列(一)中<strong>字符串</strong>部分<strong>字母与数字的映射关系</strong>了 忘记的赶快去看！</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_5">点击此处</a></p><h2 id="离散化">离散化</h2><p>【概念】：把无限空间中有限的个体<strong>映射</strong>到有限的空间中去，以 以此提高算法的时空效率。</p><p>离散化数组要求内部是<strong>有序</strong> (一般是<strong>去重</strong>的，当然也存在不去重的方法， 但是比较少见)的，可以直接通过离散化下标得到值，当然也可以通过值得到离散化下标 (通过二分实现）</p><p>【示例】：比如原数组是[0,3,1000,2,9999,2],如果将值作为下标会很麻烦，将其映射到一个离散化数组中，比如[0,2,3,1000,9999] ,用离散之后的数组的下标映射原来的元素，比如下标0代表0，下标1代表2，下标2代表3……，这样就方便后续的处理</p><p>【实现】：示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line">vector&lt;<span class="type">int</span>&gt; L;<span class="comment">//离散化数组</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//返回x在L中的下标</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">getidx</span><span class="params">(<span class="type">int</span> x)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">lower_bound</span>(L.<span class="built_in">begin</span>(),L.<span class="built_in">end</span>(),x)-L.<span class="built_in">begin</span>();</span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span><span class="number">+9</span>;</span><br><span class="line"><span class="type">int</span> a[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">cin&gt;&gt;n;<span class="comment">//获取输入的数组元素的个数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//初始化数组</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//将元素存入离散化数组中</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line">L.<span class="built_in">push_back</span>(a[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//排序并去重</span></span><br><span class="line">L.<span class="built_in">erase</span>(<span class="built_in">unique</span>(L.<span class="built_in">begin</span>(),L.<span class="built_in">end</span>()),L.<span class="built_in">end</span>()) ;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>离散化数组不会单独考察，而是和其他的数据结构一起考察，常见的形式就是给定a数组，求a的离散化数组，并通过值找到其下标。</p><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_6">点击此处</a></p><hr><h2 id="枚举">枚举</h2><p>【概念】：枚举算法是一种基本的算法思想，它通过穷举所有可能的情况来解决问题。它的基本思想是将问题的解空间中的每个可能的解都枚举出来，并进行验证和比较，找到满足问题条件的最优解或者所有解。<strong>人话就是穷举</strong>。</p><p>这里需要介绍以下解空间，因为很多时候<strong>枚举就是针对有限的解空间找到符合条件的解</strong>。解空间可以是 一个范围内的所有数字 (或二元组、字符串等数据)，或者满足某个条件的所有数字。针对解空间的性质(比如一维数组和二维数组)选择对应的循环方法枚举所有可能的结果(比如for循环或者是嵌套循环)，最终找到答案。</p><p>【例题】在蓝桥杯中考题都很简单，暴力算法足以</p><ul><li><a href="https://www.lanqiao.cn/problems/191/learning/?page=1&amp;first_category_id=1&amp;problem_id=191">1.特别数的和 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/3227/learning/?page=1&amp;first_category_id=1&amp;problem_id=3227">1.找到最多的数 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/152/learning/?page=1&amp;first_category_id=1&amp;problem_id=152">1.反倍数 - 蓝桥云课</a></li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_6">点击此处</a></p><hr><h2 id="模拟">模拟</h2><p>【概念】：模拟算法通过<strong>模拟实际情况来解决问题</strong>，一般容易理解但是实现起来比较复杂，有很多需要注意的细节，或者是一些所谓很“麻烦”的东西。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/549/learning/?page=1&amp;first_category_id=1&amp;problem_id=549">1.扫雷 - 蓝桥云课</a> 还有一种解题的方法是在原有数组的基础上外加上两行两列的0，这样就不需要多层嵌套和max与min函数使用了，直接进行判断即可</li><li><a href="https://www.lanqiao.cn/problems/551/learning/?page=1&amp;first_category_id=1&amp;problem_id=551">1.灌溉 - 蓝桥云课</a> 和上一题类似，但是要注意<strong>动态更新</strong></li><li><a href="https://www.lanqiao.cn/problems/498/learning/?page=1&amp;first_category_id=1&amp;problem_id=498">1.回文日期 - 蓝桥云课</a> 此题非常考验细节，涉及到数字与字符串之间的转换，日期格式的修改等，需要写多个函数实现</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_6">点击此处</a></p><h2 id="前缀和">前缀和</h2><p>【概念】：prefix表示前缀和，前缀和由一个用户输入的数组生成。对于一个数组a[] (下标从1开始)，我们定义一个前缀和数组prefix[]，满足：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>x</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mi>i</mi></msubsup><mi>a</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">prefix[i]=\sum_{j=1}^{i}a[j]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal">re</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal">x</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4004em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9646em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span></span></span></span> .比如prefix[1]=a[1],prefix[3]=a[1]+a[2]+a[3]，以此类推。</p><p>【性质】：后一项=前一项+原数组对应位的元素，即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>x</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>=</mo><msubsup><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>1</mn></mrow><mrow><mi>i</mi><mo>−</mo><mn>1</mn></mrow></msubsup><mi>a</mi><mo stretchy="false">[</mo><mi>j</mi><mo stretchy="false">]</mo><mo>+</mo><mi>a</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo><mo>=</mo><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>x</mi><mo stretchy="false">[</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo><mo>+</mo><mi>a</mi><mo stretchy="false">[</mo><mi>i</mi><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">prefix[i]=\sum_{j=1}^{i-1}a[j]+a[i]=prefix[i-1]+a[i]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal">re</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal">x</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.4004em;vertical-align:-0.4358em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9646em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal">re</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal">x</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mopen">[</span><span class="mord mathnormal">i</span><span class="mclose">]</span></span></span></span></p><p>在实际应用中prefix可以以O(1)的时间复杂度<strong>求数组a[]的一段区间的和</strong>：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>u</mi><mi>m</mi><mo stretchy="false">(</mo><mi>l</mi><mo separator="true">,</mo><mi>r</mi><mo stretchy="false">)</mo><mo>=</mo><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>x</mi><mo stretchy="false">[</mo><mi>r</mi><mo stretchy="false">]</mo><mo>−</mo><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>x</mi><mo stretchy="false">[</mo><mi>l</mi><mo>−</mo><mn>1</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">sum(l, r) = prefix[r] - prefix[l - 1]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">u</span><span class="mord mathnormal">m</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal">re</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal">x</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal">re</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">i</span><span class="mord mathnormal">x</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span></span></span></span>但是注意，prefix是一种预处理算法，<strong>只适用于a数组为静态数组的情况</strong>，即a数组中的元素在区间和查询过程中不会进行修改。</p><p>【实现】：示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//初始化前缀和数组</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)<span class="comment">//prefix[0]=a[0] 一般会设置a[0] = 0</span></span><br><span class="line">&#123;</span><br><span class="line">  prefix[i] = prefix[i<span class="number">-1</span>]+a[i];<span class="comment">//这里运用到其性质。</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3382/learning/?page=1&amp;first_category_id=1&amp;problem_id=3382">1.区间次方和 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/3419/learning/?page=1&amp;first_category_id=1&amp;problem_id=3419">1.小郑的蓝桥平衡串 - 蓝桥云课</a></li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_7">点击此处</a></p><h2 id="时空复杂度">时空复杂度</h2><p>关于其概念在数据结构中有详细的解释，没有基础的读者可以参考以下链接<a href="https://www.hello-algo.com/chapter_computational_complexity/performance_evaluation/">2.1  算法效率评估 - Hello 算法</a>.我们主要考虑的是评测机 时间与空间的限制。</p><p>一般来说，评测机1秒大约可以跑2e8次运算，我们要尽可能地让我们的程序运算规模数量级控制在1e8以内。而题目限制的空间一般是128MB，相当于<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>32</mn><mo>×</mo><msup><mn>2</mn><mn>20</mn></msup></mrow><annotation encoding="application/x-tex">32\times 2^{20}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">32</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">20</span></span></span></span></span></span></span></span></span></span></span></span> 个int，很少会有空间不足的情况，一旦出现空间不足的情况请优先考虑是否出现了栈溢出或者死循环的问题。</p><p>【示例】：斐波那契数列实现</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">fibonacci</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="keyword">if</span>(n&lt;=<span class="number">1</span>)</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="keyword">return</span> n;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="built_in">fibonacci</span>(n<span class="number">-1</span>)+<span class="built_in">fibonacci</span>(n<span class="number">-2</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="type">int</span> n;</span><br><span class="line">  cout&lt;&lt;<span class="string">&quot;请输入一个数: &quot;</span>;</span><br><span class="line">  cin&gt;&gt;n;</span><br><span class="line"></span><br><span class="line">  <span class="type">int</span> result = <span class="built_in">fibonacci</span>(n);</span><br><span class="line">  cout&lt;&lt;<span class="string">&quot;对应位置斐波那契数列的值是:&quot;</span>&lt;&lt;result&lt;&lt;endl;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>时空复杂度分析：时间复杂度：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msup><mn>2</mn><mi>n</mi></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(2^n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>每个递归调用会产生两个额外的递归调用，因此递归深度为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mi>n</mi></msup></mrow><annotation encoding="application/x-tex">2^n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span>，其中n是斐波那契数列的位置。空间复杂度：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>在斐波那契数列的递归算法中，递归深度为n，因此需要的堆栈空间为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>.注意，一<strong>般来说堆栈空间只给8MB，需要注意递归深度不宜过深</strong>，一般不宜超过1e6层，</p><h2 id="双指针">双指针</h2><p>【概念】：双指针算法是一种常用的<strong>算法技巧</strong>，它通常用于在数组或字符串中进行快速查找、匹配、排序或移动操作。其“指针”不一定是C\C++中的指针，也可以是是下标等。</p><p>常见的分类如下</p><h3 id="对撞指针">对撞指针</h3><p>【概念】：指的是两个指针left、right (简写为l,r)分别指向序列第一个元素和最后一个元素然后l指针不断递增，r不断递减，直到两个指针的值相撞或错开(即l&gt;=r)，或者满足其他要求的特殊条件为止。常用于解决字符串和有序数组查找相关的问题。</p><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1371/learning/?page=1&amp;first_category_id=1&amp;problem_id=1371">1.回文判定 - 蓝桥云课</a> 用双指针或者是将其反转比较均可实现</li></ul><h3 id="快慢指针">快慢指针</h3><p>【概念】：指的是两个指针从同一侧开始遍历序列，且移动的步长一个快一个慢。移动快的指针被称为快指针，移动慢的指针被称为慢指针。<strong>两个指针以不同速度、不同策略移动</strong>，直到快指针移动到数组尾端，或者两指针相交，或者是其他条件</p><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/1372/learning/?page=1&amp;first_category_id=1&amp;problem_id=1372">1.美丽的区间 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/1621/learning/?page=1&amp;first_category_id=1&amp;problem_id=1621">1.挑选子串 - 蓝桥云课</a></li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_7">点击此处</a></p><h2 id="贪心">贪心</h2><p>【概念】：每一步都选择局部最优解，而尽量不考虑对后续的影响，最终达到全局最优解。<strong>贪心是一种算法思想</strong>而不是一种具体的数据结构或者是构造。</p><p>【实现】：参考的解答步骤如下</p><ol><li>确定问题的最优子结构(贪心往往和排序、优先队列等一起出现)。</li><li>构建贪心选择的策略，可能通过“分类讨论”、“最小代价”、“最大价值”等方式来思考贪心策略。简单验证贪心的正确性，采用句式一般是：这样做一定不会使得结果变差、不存在比当前方案更好的方案等等。</li><li>通过贪心选择逐步求解问题，直到得到最终解。</li></ol><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3412/learning/?page=1&amp;first_category_id=1&amp;problem_id=3412">1.最小化战斗力差距 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/545/learning/?page=1&amp;first_category_id=1&amp;problem_id=545">1.谈判 - 蓝桥云课</a> 使用了优先级队列，当然用栈的话也是一样的道理</li><li><a href="https://www.lanqiao.cn/problems/532/learning/?page=1&amp;first_category_id=1&amp;problem_id=532">1.纪念品分组 - 蓝桥云课</a> 使用了双指针的小技巧</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_8">点击此处</a></p><h2 id="位运算">位运算</h2><p>【概念】：位运算是一种对二进制数的位进行操作的运算方式。它直接对二进制数的每一位进行逻辑操作，而不考虑整个数的数值大小，一般情况下，位运算中每一位都相互独立，各自运算得出结果 （左右移除外）</p><p>一般情况下位运算只能应用于整数(而且一般是非负数)，而且在计算机中整数是以补码的形式存储的，而正数的源码=补码。</p><p>以下知识在《数字电路技术》中有详细的解释，这里主要讲解算法中常用的部分</p><h3 id="按位与and">按位与and(&amp;)</h3><p>两个位为1时才为1。</p><p>【性质】：两个数字做与运算，结果不会变大</p><h3 id="按位或or">按位或or(|)</h3><p>有一个位为1时就为1。</p><p>【性质】：两个数字做或运算，结果不会变小</p><h3 id="按位异或xor">按位异或xor(^)</h3><p>两个位不同时为1，相同为0。</p><p>异或的性质</p><table><thead><tr><th>规律</th><th>公式</th></tr></thead><tbody><tr><td>交换律</td><td><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊕</mo><mi>y</mi><mo>=</mo><mi>y</mi><mo>⊕</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x\oplus y = y \oplus x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></td></tr><tr><td>结合律</td><td><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊕</mo><mo stretchy="false">(</mo><mi>y</mi><mo>⊕</mo><mi>z</mi><mo stretchy="false">)</mo><mo>=</mo><mo stretchy="false">(</mo><mi>x</mi><mo>⊕</mo><mo stretchy="false">)</mo><mi>y</mi><mo>⊕</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x\oplus (y\oplus z) = (x\oplus)y\oplus z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mord">⊕</span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></td></tr><tr><td>自反性</td><td><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊕</mo><mi>x</mi><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">x\oplus x = 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></td></tr><tr><td>零元素</td><td><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊕</mo><mn>0</mn><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">x\oplus 0 = x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span></td></tr><tr><td>逆运算</td><td><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mo>⊕</mo><mi>y</mi><mo>=</mo><mi>z</mi></mrow><annotation encoding="application/x-tex">x\oplus y = z</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span> 则有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>z</mi><mo>⊕</mo><mi>y</mi><mo>=</mo><mi>x</mi></mrow><annotation encoding="application/x-tex">z\oplus y = x</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊕</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> 两边同时异或y，低消掉</td></tr></tbody></table><h3 id="按位取反">按位取反(~)</h3><p>0变成1，1变成0。</p><p>一般情况下用于无符号整数，避免符号位取反。</p><h3 id="按位左移">按位左移(&lt;&lt;)</h3><p>左移(&lt;&lt;)操作将一个数的二进制表示向左移动指定的位数。移动后，低位补0，如果数据类型为有符号整型，注意移动的时候不要移动到符号位上，或者干脆使用无符号整型。1会移动到符号位.</p><p>【性质】：左移操作相当于对原数进行乘以2的幂次方的操作。比如5&lt;&lt;3 相当于 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>5</mn><mo>×</mo><msup><mn>2</mn><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">5 \times 2^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">5</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span></p><h3 id="按位左移-v2">按位左移(&lt;&lt;)</h3><p>右移(&gt;&gt;)操作将一个数的二进制表示向右移动指定的位数。移动后，一般情况高位补0，如果数据类型为有符号整型，注意移动的时候让符号位为0，或者干脆使用无符号整型。如果符号位上有1不会被移走，这是负数位移的规则</p><p>【性质】：右移操作相当于对原数进行除以2的幂次方的操作。比如5&gt;&gt;3 相当于 5 ÷ <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">2^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span> 并<strong>向下取整</strong></p><h3 id="按位设置">按位设置</h3><p>C++代码示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//得到的结果是11100000 00000000 00000000 00000000</span></span><br><span class="line">cout&lt;&lt;<span class="built_in">bitset</span>&lt;<span class="number">32</span>&gt;((<span class="number">1</span>&lt;&lt;<span class="number">31</span>)&gt;&gt;<span class="number">2</span>)&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="位运算的应用">位运算的应用</h3><ol><li>判断奇偶性：x&amp;1,结果是1说明是奇数，0为偶数。原理就是判断最后一个位是1还是0.</li><li>获取二进制某一位：x&gt;&gt;i&amp;1结果必然为0或1，表示x的二进制表示中的第i位。</li><li>修改二进制中的某一位为1： x I (1 &lt;&lt; i)将x的第i位或上1，则x[i]变为1，其他位上或上0没有影响。如果读者做的题够多的话，会发现这个方法和字符型字母大小写转换是类似的，在倒数第6位修改为1可以实现大写转小写(原理，字母大写与小写相差32)</li><li>快速判断一个数字是否为2的幂次方：X &amp; (x- 1) 如果x为2的幕次方，则x的二进制表示中只有一个1,X－1就有很多个连续的1并且和x的1没有交集，两者与运算一定为0，可以证明其他情况必然不为0。</li><li>获取二进制位中最低位的1：lowbit(x) =x &amp; -x 如果x=(010010)，则lowbit(x)=(000010).常用于数据结构树状数组中。</li><li>……</li></ol><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/1331/learning/?page=1&amp;first_category_id=1&amp;problem_id=1331">1.二进制中 1 的个数 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/3691/learning/?page=1&amp;first_category_id=1&amp;problem_id=3691">1.区间或 - 蓝桥云课</a></li><li><a href="https://www.lanqiao.cn/problems/3400/learning/?page=1&amp;first_category_id=1&amp;problem_id=3400">1.异或森林 - 蓝桥云课</a></li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_8">点击此处</a></p><h2 id="排序">排序</h2><p>在实际解决题目的时候一般要求<strong>掌握排序的使用方法</strong>(比如C++中的sort)，而不会侧重于排序的实现。</p><h3 id="插入排序">插入排序</h3><p>【概念】：插入排序是一种简单直观的排序算法，其基本思想是将待排序的元素逐个插入到已排序序列的合适位置中，使得已排序序列逐渐扩大，从而逐步构建有序序列，最终得到完全有序的序列。生活中的例子就是打扑克牌</p><p>【实现】：就是插入+移动</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//i表示当前要确定的位置</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">  <span class="comment">//此时[1,i-1]已经为有序的数组</span></span><br><span class="line">  <span class="type">int</span> val = a[i],j;</span><br><span class="line">  <span class="comment">//将val与a[j-1]比较,如果小于的话就将a[j-1]后移动一格,给val提供位置</span></span><br><span class="line">  <span class="keyword">for</span>(j = i;j&gt;<span class="number">1</span> &amp;&amp; val &lt;a[j<span class="number">-1</span>];j--)</span><br><span class="line">  &#123;</span><br><span class="line">    a[j] = a[j<span class="number">-1</span>];</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//当循环跳出时，j=1或者val&gt;=a[j]，此时a[j]已经往后移动,j为给val空出来的位置</span></span><br><span class="line">  a[j] = val;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/3225/learning/?page=1&amp;first_category_id=1&amp;problem_id=3225">1.宝藏排序Ⅰ - 蓝桥云课</a>  如果你知道C++中的sort，这题就直接秒了o(<em>￣▽￣</em>)o</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_8">点击此处</a></p><h3 id="归并排序">归并排序</h3><p>【概念】：原理是将一个数组分成两个子数组，将子数组向下递归的排序后（当数组中仅有一个元素值无需再排序了，直接返回），得到两个有序数组，然后进行O(n)的合并，最终合并成有序的原数组。</p><p>【实现】：先递归实现两边分别有序，然后一点点排序</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e5</span><span class="number">+9</span>;</span><br><span class="line"><span class="comment">//注意要先声明b数组，否则会报错</span></span><br><span class="line"><span class="type">int</span> b[N];</span><br><span class="line"></span><br><span class="line"><span class="comment">//归并排序算法实现</span></span><br><span class="line"><span class="comment">//a为要排序的数组，l、r为 区间的左右端点 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">MergeSort</span><span class="params">(<span class="type">int</span> a[],<span class="type">int</span> l,<span class="type">int</span> r)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//当递归到子数组大小为1时停止排序 </span></span><br><span class="line"><span class="keyword">if</span>(l == r)<span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> mid = (l+r)/<span class="number">2</span>;</span><br><span class="line"><span class="comment">//左右部分分别递归排序 </span></span><br><span class="line"><span class="built_in">MergeSort</span>(a,l,mid);</span><br><span class="line"><span class="built_in">MergeSort</span>(a,mid<span class="number">+1</span>,r);</span><br><span class="line"></span><br><span class="line"><span class="comment">//排序完后a[l,mid]和[mid+1,r]都是有序的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//将两个排序后的数组合并放入b</span></span><br><span class="line"><span class="comment">//pl是左半边指向要比较的数的下标，pr是右半边指向要比较的数的下标，pb是b中指向要插入位置的下标 </span></span><br><span class="line"><span class="type">int</span> pl = <span class="number">1</span>,pr = mid<span class="number">+1</span>,pb=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span>(pl &lt;=mid || pr&lt;=r) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(pl&gt;mid)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//左边数组已经放完</span></span><br><span class="line">b[pb++] =a[pr++];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span>(pr &gt; r) </span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//右半边已经放完</span></span><br><span class="line">b[pb++] = a[pl++];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//两边都还有元素，就比较并将小的放在b数组</span></span><br><span class="line"><span class="keyword">if</span>(a[pl]&lt;a[pr]) </span><br><span class="line">&#123;</span><br><span class="line">b[pb++] = a[pl++];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">b[pb++] = a[pr++];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//完成后复制回原数组</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=r;i++) </span><br><span class="line">&#123;</span><br><span class="line">a[i] = b[i];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3226/learning/?page=1&amp;first_category_id=1&amp;problem_id=3226">1.宝藏排序Ⅱ - 蓝桥云课</a> 尝试用归并排序的方法实现</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_9">点击此处</a>  注意文件名为<code>lanqiao_3226_MergeSort</code>表明此题是用归并排序实现的</p><h3 id="快速排序">快速排序</h3><p>【概念】：快速排序是一种基于分治法的排序方法，原理是将一个数组分成两个子数组，其中一个子数组的所有元素都小于另一个子数组的元素，然后递归地对这两个子数组进行排序。</p><p>【实现】：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">//快速排序算法实现</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//和归并排序不同的是只需要将两个排完序的数组直接前后拼接即可 </span></span><br><span class="line"><span class="comment">//不过要求左边的数组所有元素均小于右边的最小的元素 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">QuickSort</span><span class="params">(<span class="type">int</span> a[],<span class="type">int</span> l,<span class="type">int</span> r)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(l&lt;r)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> mid = <span class="built_in">Partition</span>(a,l,r);</span><br><span class="line"><span class="built_in">QuickSort</span>(a,l,mid<span class="number">-1</span>);</span><br><span class="line"><span class="built_in">QuickSort</span>(a,mid<span class="number">+1</span>,r);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3226/learning/?page=1&amp;first_category_id=1&amp;problem_id=3226">1.宝藏排序Ⅱ - 蓝桥云课</a> 尝试用快速排序的方法实现</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_9">点击此处</a></p><h3 id="冒泡排序">冒泡排序</h3><p>【概念】：冒泡排序的思想是每次将最大的一下一下运到最右边，然后将最右边这个确定下来，再来确定第二大的，再确定第三大的。算是排序中比较容易实现的算法，但是其复杂度过高，在较多元素排序的情况下会有超时的风险。</p><p>【实现】：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1</span>d3<span class="number">+9</span>;</span><br><span class="line"><span class="type">int</span> a[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//i表示当前要确定的位置</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = n;i&gt;=<span class="number">1</span>;i++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//j从左往右扫</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>;j&lt;=i<span class="number">-1</span>;j++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(a[j] &gt; a[j<span class="number">+1</span>])</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">swap</span>(a[j],a[j<span class="number">+1</span>]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//输出打印</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;a[i]&lt;&lt;<span class="string">&quot; \n&quot;</span>[i == n];</span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>【例题】：</p><ul><li><a href="https://www.lanqiao.cn/problems/3225/learning/?page=1&amp;first_category_id=1&amp;problem_id=3225">1.宝藏排序Ⅰ - 蓝桥云课</a> 这里为什么没有用3226题作为例题呢？因为排序的数据有1e5次方，如果使用冒泡排序就会超时，所以冒泡排序只适合数据量较少的情况。</li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_9">点击此处</a></p><h3 id="桶排序">桶排序</h3><p>【概念】：桶排序(Bucket sort)是一种非比较的排序算法。桶排序采用了一些分类和分治的思想，把元素的值域分成若干段，每一段对应一个桶。在排序的时候，首先把每一个元素放到其对应的桶中，再对每一个桶中的元素分别排序，再按顺序把每个桶中的元素依次取出，合并成最终答案。</p><p>【实现】：此算法与归并排序十分相似，不同的是这里的分段不完全像归并一样递归到1个元素的排序，而可能是多个元素的。还有就是排序的时候没有比较，算法的时间复杂度小，但是用空间换来的。步骤如下</p><ol><li>将值域分成若干段，每段对应一个桶</li><li>将待排序元素放入对应的桶中</li><li>将个桶内的元素进行排序</li><li>将桶中的元素依次取出</li></ol><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//题目链接： https://www.lanqiao.cn/problems/1314/learning/?page=1&amp;first_category_id=1&amp;problem_id=1314</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">5e5</span><span class="number">+7</span>;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"><span class="type">int</span> bucket[MAXN];<span class="comment">//一个值对应一个桶</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> x;</span><br><span class="line">cin&gt;&gt;x;</span><br><span class="line">bucket[x++];<span class="comment">//由于每个只有一个值，但是可以有多个相同值的数，所以只需要记录元素个数即可 </span></span><br><span class="line">&#125;</span><br><span class="line">    <span class="comment">//输出最终排序结果</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>;j&lt;= bucket[i];j++) <span class="comment">// 值为i的元素有bucket[i]个 </span></span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;i&lt;&lt;<span class="string">&quot; &quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>在元素值较小的情况下当然可以这样为每一个值分配一个桶，但是如果值可以是1e9甚至更多呢？那么就必须要将其分段然后排序了</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//题目链接： https://www.lanqiao.cn/problems/1314/learning/?page=1&amp;first_category_id=1&amp;problem_id=1314</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> MAXN = <span class="number">5e5</span><span class="number">+7</span>;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line"></span><br><span class="line">vector&lt;<span class="type">int</span>&gt; bucket[MAXN];</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> x;</span><br><span class="line">cin&gt;&gt;x;</span><br><span class="line">bucket[x/<span class="number">1000</span>].<span class="built_in">push_back</span>(x);<span class="comment">//将值域分为(最大值/1000)段，每一段对应一个桶</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;MAXN;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="comment">//对每一个桶排序，方法随意</span></span><br><span class="line"><span class="built_in">sort</span>(bucket[i]);</span><br><span class="line">&#125;</span><br><span class="line">    <span class="comment">//输出最终排序结果</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;MAXN;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">auto</span> item:bucket[i])</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;item&lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><blockquote><p>总结：对于数据量较大但值域较小的数据，如<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>&gt;</mo><msup><mn>10</mn><mn>7</mn></msup><mo separator="true">,</mo><msub><mi>a</mi><mi>i</mi></msub><mo>&lt;</mo><msup><mn>10</mn><mn>6</mn></msup></mrow><annotation encoding="application/x-tex">n&gt;10^{7},a_i&lt;10^{6}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">7</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">6</span></span></span></span></span></span></span></span></span></span></span></span>，可以做到每个值对应一个桶，桶排序的时间复杂度为O(n)。推荐使用桶排序。</p></blockquote><h3 id="选择排序">选择排序</h3><p>【概念】：选择排序的思想和冒泡排序类似，是每次找出最大的然后直接放到右边对应位置，然后将最右边这个确定下来(而不是一个一个地交换过去)。</p><p>【实现】:</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e3</span><span class="number">+9</span>;</span><br><span class="line"><span class="type">int</span> a[N];</span><br><span class="line"></span><br><span class="line"><span class="comment">//注意这样排序出来的结果是从小到大</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//i表示当前要确定的位置</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = n;i&gt;=<span class="number">1</span>;i--) </span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> max_id = <span class="number">1</span>;<span class="comment">//初始化为1</span></span><br><span class="line"><span class="comment">//j从左往右扫求出max_id</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">1</span>;j&lt;=i;j++) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(a[j] &gt; a[max_id])</span><br><span class="line">&#123;</span><br><span class="line">max_id = j;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">swap</span>(a[max_id],a[i]);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//输出排序结果</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">1</span>;i&lt;=n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;a[i]&lt;&lt;<span class="string">&quot; \n&quot;</span>[i == n];</span><br><span class="line">&#125;</span><br><span class="line">&#125; </span><br></pre></td></tr></table></figure><p>【例题】</p><ul><li><a href="https://www.lanqiao.cn/problems/3225/learning/?page=1&amp;first_category_id=1&amp;problem_id=3225">1.宝藏排序Ⅰ - 蓝桥云课</a></li></ul><p>本部分例题解决实现代码链接：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup/tree/main/2_10">点击此处</a></p><h2 id="参考">参考</h2><ol><li><a href="https://leetcode.cn/circle/discuss/E3yavq/">力扣刷题攻略</a>  读者可以在这里参考刷题。</li><li>蓝桥云课C++班，作者谢子杨</li></ol>]]></content>
    
    
    <summary type="html">总结了C/C++赛道蓝桥杯常见的题型以及背后的算法原理,为读者提供一个刷题和总结的参考。</summary>
    
    
    
    <category term="algorithm" scheme="https://lloydkai.cn/categories/algorithm/"/>
    
    
    <category term="C" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>算法系列(一)蓝桥杯及其知识体系</title>
    <link href="https://lloydkai.cn/posts/lanqiaocup-series-one/"/>
    <id>https://lloydkai.cn/posts/lanqiaocup-series-one/</id>
    <published>2024-12-14T14:16:54.000Z</published>
    <updated>2026-04-23T01:45:53.877Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/rVx9ogHB31wf4mJ.jpg" alt></p><h1>蓝桥杯及其知识体系</h1><blockquote><p>以下内容借鉴了参考中的视频和其他部分。当前还在持续更新中.我的代码库参考：<a href="https://github.com/lloyd-kai/cpp-lanqiaocup">lloyd-kai/cpp-lanqiaocup</a></p><p>一放假就有点放纵自我了，<strong>不能再堕落下去了，一定要出重拳</strong>！o(<em>￣▽￣</em>)o 今天就要吹响开始学习的号角</p><p>要想办法能够在节假日和休闲时间尽可能做到自律，而不是三分钟热度</p></blockquote><h2 id="蓝桥杯系列">蓝桥杯系列</h2><h3 id="准备工作">准备工作</h3><ol><li><p>蓝桥杯使用的C++是11版本的，注意不要使用过多的新语法</p></li><li><p><code>#include &lt;bits/stdc++.h&gt; </code>考试推荐的万能导入头文件，但是工作的时候不要用</p></li></ol><h3 id="字符串">字符串</h3><blockquote><p>提醒：C语言和C++具有很多相同的函数。</p></blockquote><h4 id="常见的函数及其使用-C语言">常见的函数及其使用(C语言)</h4><p><strong>scanf</strong></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d %d&quot;</span>，&amp;a,&amp;b); <span class="comment">//表示接收两个int类型的输入 并将其赋值给a和b，注意除了字符串以外都要加上&amp; 因为字符串本身就是指针</span></span><br><span class="line"></span><br><span class="line"><span class="type">char</span> s[<span class="number">10</span>];<span class="comment">//定义一个字符串数组</span></span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>,s);<span class="comment">// %s读取字符串，并复制给s，但是如果读取字符串的时候读取到空格或者回车就会停止。</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%s&quot;</span>,s);<span class="comment">// 例如输入为Hello tom 输出结果为 Hello</span></span><br></pre></td></tr></table></figure><p>常见的其他标识符</p><table><thead><tr><th>类型</th><th>对应标识符</th></tr></thead><tbody><tr><td>int</td><td>%d</td></tr><tr><td>double</td><td>%lf</td></tr><tr><td>char</td><td>%c</td></tr><tr><td>char[]</td><td>%s</td></tr><tr><td>long long</td><td>%lld</td></tr></tbody></table><p><strong>正则表达式在scanf中的应用</strong></p><p>例如</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="type">char</span> s[<span class="number">15</span>];</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%[^\n]&quot;</span>,s);<span class="comment">//这里的正则表达式的意思是只要不是回车就读进去，非常好用</span></span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%s&quot;</span>,s);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>strcpy</strong></p><p>实现字符串复制的功能 具体看 C/C++参考文档 官网如下<a href="https://zh.cppreference.com/w/%E9%A6%96%E9%A1%B5">cppreference.com</a></p><p><strong>strcat</strong></p><p>实现字符串拼接的功能，函数原型：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">char</span> *<span class="title function_">strcat</span><span class="params">(<span class="type">char</span> *<span class="keyword">restrict</span> dest, <span class="type">const</span> <span class="type">char</span> *<span class="keyword">restrict</span> src )</span>;</span><br></pre></td></tr></table></figure><p><strong>strcmp</strong></p><p>实现字符串比较的功能</p><p>函数原型</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">strcmp</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *lhs, <span class="type">const</span> <span class="type">char</span> *rhs )</span>;</span><br></pre></td></tr></table></figure><p><strong>strlen</strong></p><p>测量字符串长度</p><h4 id="常见的函数及其使用-C">常见的函数及其使用(C++)</h4><p><strong>cin与cout</strong></p><p>它们的作用和scanf与printf一样，但是有一些差别。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">double</span> a,b</span><br><span class="line">cin&gt;&gt;a&gt;&gt;b;<span class="comment">//输入为2 3</span></span><br><span class="line">cout&lt;&lt;fixed&lt;&lt;<span class="built_in">setprecision</span>(<span class="number">3</span>)&lt;&lt;a&lt;&lt;<span class="string">&#x27; &#x27;</span>&lt;&lt;b&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;<span class="comment">//输出为2.000 3.000 这里的setprecision()是设置保留小数位数</span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="type">char</span> ch;</span><br><span class="line">    cin&gt;&gt;ch;<span class="comment">//输入为a</span></span><br><span class="line">    cout&lt;&lt;ch;<span class="comment">//输出为a 这种C语言的字符串建议使用scanf与printf 性能更好</span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    <span class="type">char</span> s[<span class="number">10</span>];</span><br><span class="line">    cin&gt;&gt;s;<span class="comment">//输入lan qiao</span></span><br><span class="line">    cout&lt;&lt;s;<span class="comment">//输出为lan  注意cin输入字符串也是遇到空格或者回车就结束 </span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    string s;</span><br><span class="line">    <span class="built_in">getline</span>(cin,s);<span class="comment">//输入为lan qiao此函数能获取一行的输入，包括空格</span></span><br><span class="line">    cout&lt;&lt;s;<span class="comment">//输出为lan qiao</span></span><br><span class="line">    </span><br><span class="line">    <span class="comment">//还有获取字符串的方法是是fgets()函数+输入流的方式</span></span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    string str[<span class="number">10</span>];<span class="comment">//cin的好处就是能直接将输入的数据放入容器中</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">10</span>;i++)</span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;str[i];<span class="comment">//将输入的字符串写入到str[i]中</span></span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以看见，虽然cin与cout在参数传递的时候不需要指定参数类型(自动判断变量类型), 但是cout对于浮点数和自定义的输出格式不如printf，而且cin与cout的性能相对于scanf与printf较低——由于cin和cout需要自动判断变量类型等内部原因，读写效率比scanf和printf更低，一般建议在<strong>考试时使用scanf与printf</strong>,而且需要注意：<u>要么在一个程序中使用cin与cout,要么使用scanf与printf,不推荐两者混合使用</u>。</p><p>那有没有什么办法提高cin与cout的速度呢？有，那就是<strong>取消同步流</strong>.建议使用C++风格的输入与输入函数的时候就加上这一行代码。</p><p>示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//取消同步流</span></span><br><span class="line">ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//其他操作不变</span></span><br><span class="line"><span class="type">int</span> x;</span><br><span class="line">cin&gt;&gt;x;</span><br><span class="line">cout&lt;&lt;s;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="应用及题型">应用及题型</h4><p><strong>字母与数字的映射关系</strong>：</p><p>比如题目规定出现A代表10，B代表11，就要想到A的ASCII编码是97，B的编码是98，a的ASCII编码是65，找对应关系。<br>怎么找呢？这样看，比如数字10代表A，A是A到Z字母集的开头，对应的数也应该是是数集的开头(这里指的是10),那么映射的函数就是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>n</mi><mo>−</mo><mi>c</mi><msup><mo>+</mo><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><msup><mi>A</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">f(n)=n-c+&#x27;A&#x27;</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8352em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mbin">+</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span> 其中n是输入的数字，c是数集的开头，'A’是字母集的开头，得到的结果是字母</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//数字映射为字母 10代表A  11代表B</span></span><br><span class="line"><span class="keyword">if</span>(n&gt;=<span class="number">10</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%c&quot;</span>,n<span class="number">-10</span>+<span class="string">&#x27;A&#x27;</span>);<span class="comment">//这样n为11就打印B，12就打印C，反之同理</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//字母映射为数字   ASCII编码中字符0-9对应编码为48-57.</span></span><br><span class="line"><span class="keyword">if</span>(c&gt;<span class="string">&#x27;A&#x27;</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d&quot;</span>,c-<span class="string">&#x27;A&#x27;</span>+<span class="number">10</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>字母的大小写转换</strong></p><ol><li>用ASCII码实现</li></ol><p>原理：字符A减去字符a会变为数字32.</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//小写转大写</span></span><br><span class="line"><span class="type">char</span> a = <span class="string">&#x27;a&#x27;</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%c&quot;</span>,a+(<span class="string">&#x27;A&#x27;</span>-<span class="string">&#x27;a&#x27;</span>));<span class="comment">//大写A比小写a少‘32’，但是不能直接写32或者&#x27;32&#x27;(直接写就会整形提升)，而是写(&#x27;A&#x27;-&#x27;a&#x27;)，</span></span><br><span class="line"><span class="comment">//</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//大写转化为小写同理</span></span><br><span class="line"><span class="type">char</span> b = <span class="string">&#x27;B&#x27;</span>;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%c&quot;</span>,b-(<span class="string">&#x27;A&#x27;</span>-<span class="string">&#x27;a&#x27;</span>));</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>示例：将输入的字符串大写转小写，小写转大写</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cctype&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">char</span> <span class="title">convertedCh</span><span class="params">(<span class="type">char</span> ch)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">islower</span>(ch))<span class="comment">//或者是用if(&#x27;a&#x27;&lt;=ch &amp;&amp; ch&lt;=&#x27;z&#x27;)</span></span><br><span class="line">&#123;</span><br><span class="line">ch = <span class="built_in">toupper</span>(ch);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span>(<span class="built_in">isupper</span>(ch))<span class="comment">//或者用if(&#x27;A&#x27;&lt;=ch &amp;&amp; ch&lt;=&#x27;Z&#x27;)</span></span><br><span class="line">&#123;</span><br><span class="line">ch = <span class="built_in">tolower</span>(ch);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> ch;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//将输入的字符串小写变大写，大写变小写</span></span><br><span class="line">string s;</span><br><span class="line"><span class="built_in">getline</span>(cin,s);</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>;j&lt;s.<span class="built_in">length</span>();j++)</span><br><span class="line">&#123;</span><br><span class="line">s[j] = <span class="built_in">convertedCh</span>(s[j]);</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;s&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在C/C++语言中规定，未尾以<code>\0</code>结束的字符型数组称为字符串。这里值得强调的是，只有以<code>\0</code> 结束的才能算是字符串，否则只能算作字符型数组。这在C/C++中算是一种标准。也只有以<code> \0</code>结束的字符数组才能以&quot;%s&quot;的方式用printf输出，否则输出的结果会非常奇怪。自己在char数组上构造一个字符串的时候，忘记在末尾加<code>\0</code>可能会导致访问非法内存的错误。</p><ol start="2"><li>用库函数实现</li></ol><p>islower和isupper是C++标准库中的字符分类函数，用于检查一个字符(<code>char</code>)是否为小写字母或大写字母。islower和isupper函数需要包含头文件<code>&lt;cctype&gt;</code>,也可用万能头包含。函数返回值为bool类型.tolower(char ch)可以将ch转化为小写字母，如果ch不是大写字母就不进行操作。toupper同理，将ch转为大写字母。</p><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cctype&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="type">char</span> ch1 = <span class="string">&#x27;a&#x27;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">islower</span>(ch1)) </span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;ch1&lt;&lt;<span class="string">&quot;是小写字母&quot;</span>&lt;&lt;endl;</span><br><span class="line"><span class="type">char</span> ch3 = <span class="built_in">toupper</span>(ch1);<span class="comment">//注意如果直接在cout中输入toupper(ch1)会默认将其转为int类型，所以需要用char类型的变量接收</span></span><br><span class="line">cout&lt;&lt;ch3&lt;&lt;<span class="string">&quot;是大写字母&quot;</span>&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line">    </span><br><span class="line"><span class="type">char</span> ch2 = <span class="string">&#x27;A&#x27;</span>;</span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">isupper</span>(ch2))</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;ch2&lt;&lt;<span class="string">&quot;是大写字母&quot;</span>&lt;&lt;endl;</span><br><span class="line"><span class="type">char</span> ch4 = <span class="built_in">tolower</span>(ch2);</span><br><span class="line">cout&lt;&lt;ch4&lt;&lt;<span class="string">&quot;是小写字母&quot;</span>&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>例题1</strong>：判断一个数是奇数还是偶数，但是至少10000位_(:з」∠)_ ？</p><p>分析：如果这个数<code>%2==0</code> 就是偶数，关键在于这个数<strong>数量级太大</strong>，long long也存不下，这个时候需要将其作为“字符”来看待，可以用string 或者是char[] 数组，观察可知，判断奇偶数的关键其实在于<strong>最后一位的数字，只要其为偶数，那么整个数为偶数</strong>，反之就是奇数.找最后一位就需要用strlen获取字符串的长度了，代码示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstdio&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="comment">//如果你用的是C就导入stdio.h和string.h C++的导入上述的方库</span></span><br><span class="line"><span class="type">char</span> s[<span class="number">10001</span>]</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> len;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>,s);</span><br><span class="line">len = <span class="built_in">strlen</span>(s);</span><br><span class="line"><span class="keyword">if</span>((s[len<span class="number">-1</span>]-<span class="string">&#x27;0&#x27;</span>)%<span class="number">2</span> == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;是偶数&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;是奇数&quot;</span>);</span><br><span class="line">&#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>例题2</strong>：反转输出字符串</p><p>分析：这个很简单，用C语言实现就是从后往前遍历char[]数组并输出，这里就需要使用<code>strlen()</code>函数获取到字符串的长度.C++string类有reverse函数，可以直接反转字符串。</p><p><strong>例题3</strong>：输出最后一个单词的长度</p><p>关键在于遍历读取每一个单词直到读取到文件末尾，这里就使用到C语言中的文件读取，而scanf在读取的过程中如果使用的是<code>scanf(&quot;%s&quot;,s)</code> 就会<strong>持续读取直到为空格</strong>，如果<strong>读取到文本末尾会返回EOF的值</strong>，我们就需要使用这个返回值帮助我们读取到最后一个单词。示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstdio&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstring&gt;</span></span></span><br><span class="line"><span class="type">char</span> s[<span class="number">10001</span>]</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">while</span>(<span class="built_in">scanf</span>(<span class="string">&quot;%s&quot;</span>,s)!=EOF)<span class="comment">//读取到最后一个单词的时候才会退出 </span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">continue</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%d\n&quot;</span>,<span class="built_in">strlen</span>(s));</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="刷题练习">刷题练习</h4><p><a href="https://www.lanqiao.cn/problems/?first_category_id=1&amp;second_category_id=6&amp;difficulty=30">题库 - 蓝桥云课</a></p><ul><li>编号1</li></ul><h3 id="日期">日期</h3><p><strong>经典题型1</strong> 找闰年</p><p>分析：年份非整百且能被4整除的为闰年和年份能被400整除的是闰年</p><p>用C语言表示为</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span>(year % <span class="number">400</span> == <span class="number">0</span>||(year % <span class="number">100</span> != <span class="number">0</span> &amp;&amp; year %<span class="number">4</span> == <span class="number">0</span> ) ) <span class="comment">//这里有个小技巧，先将判断量小的放前面再将判断量大的放后面，优化一定的时间。</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>经典题型2</strong>：星期几</p><p>分析：经常会遇到别人问你几月几号是星期几的情况，如何不查日历，直接用程序算出来呢？一种最简单的方法是，记住很久以前的<br>某一天是星期几，比如公元1年1月1日是星期一。然后一天一天模拟，算出日期是星期几。这种方法容易理解，但是实现起来代码可能比较长。除此之外，有一个公式可以快速地根据日期计算这一天是星期几，这被称为<strong>蔡基姆拉尔森计算公式</strong>。</p><p>假设星期为w,年份为y，月份为m,日期为d(第几天)，公式为</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>w</mi><mo>=</mo><mo stretchy="false">(</mo><mi>d</mi><mo>+</mo><mn>2</mn><mi>m</mi><mo>+</mo><mn>3</mn><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mn>1</mn><mo stretchy="false">)</mo><mi mathvariant="normal">/</mi><mn>5</mn><mo>+</mo><mi>y</mi><mo>+</mo><mi>y</mi><mi mathvariant="normal">/</mi><mn>4</mn><mo>−</mo><mi>y</mi><mi mathvariant="normal">/</mi><mn>100</mn><mo>+</mo><mi>y</mi><mi mathvariant="normal">/</mi><mn>400</mn><mo stretchy="false">)</mo><mi mathvariant="normal">%</mi><mn>7</mn></mrow><annotation encoding="application/x-tex">w = (d + 2m + 3(m+1)/5+y+y/4-y/100+y/400)\%7</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">3</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mord">/5</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/4</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/400</span><span class="mclose">)</span><span class="mord">%7</span></span></span></span></span></p><p>然后把计算出来的w加上1就是真正的星期几了,<strong>注意每年的1,2月要当成上一年13,14月计算，上述的除法均为整除</strong></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">ComDay</span><span class="params">(<span class="type">int</span> y,<span class="type">int</span> m,<span class="type">int</span> d)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span>(m&lt;=<span class="number">2</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        m+=<span class="number">12</span>;</span><br><span class="line">        y--;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> (d+<span class="number">2</span>*m+<span class="number">3</span>*(m+<span class="number">1</span>)/<span class="number">5</span>+y+y/<span class="number">4</span>-y/<span class="number">100</span>+y/<span class="number">400</span>)%<span class="number">7</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>经典题型3</strong>：计算日期并按格式输出<br>分析：要考虑到闰年二月时间的变化，不同月份的天数不同。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstdio&gt;</span></span></span><br><span class="line"><span class="type">int</span> day[<span class="number">13</span>] = &#123;<span class="number">0</span>,<span class="number">31</span>,<span class="number">28</span>,<span class="number">31</span>,<span class="number">30</span>,<span class="number">31</span>,<span class="number">30</span>,<span class="number">31</span>,<span class="number">31</span>,<span class="number">30</span>,<span class="number">31</span>,<span class="number">30</span>,<span class="number">31</span>&#125;</span><br><span class="line"><span class="type">int</span> <span class="built_in">main</span>()</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> y,m,d,k;</span><br><span class="line"><span class="built_in">scanf</span>(<span class="string">&quot;%d%d%d%d&quot;</span>,&amp;y,&amp;m,&amp;d,&amp;k);</span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i =<span class="number">1</span>;i &lt;=k;i++)&#123;</span><br><span class="line"><span class="number">1</span>f((y%<span class="number">100</span>!=<span class="number">0</span> &amp;&amp; y%<span class="number">4</span>=<span class="number">0</span>)||y%<span class="number">400</span>=<span class="number">0</span>)&#123;</span><br><span class="line">day[<span class="number">2</span>]= <span class="number">29</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span>&#123;</span><br><span class="line">day[<span class="number">2</span>]= <span class="number">28</span>;</span><br><span class="line">&#125;</span><br><span class="line">d++;</span><br><span class="line"><span class="keyword">if</span> (d == day[m])&#123;</span><br><span class="line">d=<span class="number">1</span>;</span><br><span class="line">m++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (m == <span class="number">13</span>)&#123;</span><br><span class="line">m=<span class="number">1</span>;</span><br><span class="line">y++;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">printf</span>(<span class="string">&quot;%04d-%02d-%02d\n&quot;</span>,y,m,d);</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>技巧：</p><p><strong>判断与穷举、范围、布尔值的转化</strong>：对于每个月份有多少天这种规律比较复杂的一系列数，用if判断显得臃肿，而将其所有情况写在数组里面，用下标代替判断更为有效。对于字符不能是A-Z这种限定条件，不要用穷举而是用范围的方式(比如<code>if(c&gt;='A' &amp;&amp; C&lt;='Z')</code>),这样更加简洁。对于字符串是否相等的问题，有时候不需要flag标志进行判断，而可以用链式方式简化</p><h3 id="排序-C-使用sort">排序(C++使用sort)</h3><p>sort是一个C++已经为我们实现好的工具，当我们要用它时，需要先引入一个算法的库一&lt;algorithm&gt;。需要说明的是，sort可以排序任何类型的元素，包括我们自己定义的结构体。我们将需要在C++文件的开始位置加上：<code>#include &lt;algorithm&gt;</code></p><p><strong>函数原型：</strong></p><ul><li><p><code>sort(iterator beg, iterator end, _Pred);  </code></p><p>// 按值查找元素，找到返回指定位置迭代器，找不到返回结束迭代器位置<br>//  beg    开始迭代器  或者是起始地址<br>//  end    结束迭代器 或者是结束地址的下一位(<code>arr+size</code>)<br>// _Pred  谓词 <strong>也就是排序方法</strong> 比如greater就是从大到小排序</p></li></ul><p><strong>示例：</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">myPrint</span><span class="params">(<span class="type">int</span> val)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">cout &lt;&lt; val &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">test01</span><span class="params">()</span> </span>&#123;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v;</span><br><span class="line">v.<span class="built_in">push_back</span>(<span class="number">10</span>);</span><br><span class="line">v.<span class="built_in">push_back</span>(<span class="number">30</span>);</span><br><span class="line">v.<span class="built_in">push_back</span>(<span class="number">50</span>);</span><br><span class="line">v.<span class="built_in">push_back</span>(<span class="number">20</span>);</span><br><span class="line">v.<span class="built_in">push_back</span>(<span class="number">40</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//sort默认从小到大排序</span></span><br><span class="line"><span class="built_in">sort</span>(v.<span class="built_in">begin</span>(), v.<span class="built_in">end</span>());</span><br><span class="line">for_each(v.<span class="built_in">begin</span>(), v.<span class="built_in">end</span>(), myPrint);</span><br><span class="line">cout &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line"><span class="comment">//从大到小排序</span></span><br><span class="line"><span class="built_in">sort</span>(v.<span class="built_in">begin</span>(), v.<span class="built_in">end</span>(), <span class="built_in">greater</span>&lt;<span class="type">int</span>&gt;());</span><br><span class="line">for_each(v.<span class="built_in">begin</span>(), v.<span class="built_in">end</span>(), myPrint);</span><br><span class="line">cout &lt;&lt; endl;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//对数组排序</span></span><br><span class="line">    <span class="type">int</span> a[<span class="number">1000</span>];</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">1000</span>;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        a[i] = i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">sort</span>(a,a<span class="number">+1000</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="built_in">test01</span>();</span><br><span class="line"></span><br><span class="line"><span class="built_in">system</span>(<span class="string">&quot;pause&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>总结</strong>：sort属于开发中最常用的算法之一，需熟练掌握</p><h4 id="进阶：自定义-Pred参数">进阶：自定义 _Pred参数</h4><p>对于一般的容器谓词可以直接用greater,但是如果是类的排序或者是其他具有多个成员变量的对象的排序呢？这个时候就需要自己定义一个谓词，将需要进行比较的对象作为形参，以某种比较方式进行比较，最后要返回布尔值。为真就会被排到容器前面，假就会排在后面。</p><p>示例如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//返回值必须是bool</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y)</span></span>&#123;</span><br><span class="line"><span class="comment">//这里是比较x与y个位大小，为真返回true，即只要为真的都在前面，为false都在后面。</span></span><br><span class="line"><span class="keyword">return</span> x % <span class="number">10</span> &gt; y % <span class="number">10</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>使用lambda表达式定义排序方法</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在&quot;Sort.cpp&quot;文件内</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_Sort</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化</span></span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v= &#123;<span class="number">5</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="number">9</span>,<span class="number">11</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//对数组排序</span></span><br><span class="line"><span class="built_in">sort</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>(),[](<span class="type">const</span> <span class="type">int</span> &amp;u,<span class="type">const</span> <span class="type">int</span> &amp;v) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> u&gt;v;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;v.<span class="built_in">size</span>();i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;v[i]&lt;&lt;<span class="string">&#x27; &#x27;</span> ;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//在main.cpp文件</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="comment">//测试排序函数</span></span><br><span class="line"><span class="built_in">Test_Sort</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当然可以用<strong>运算符重载</strong>直接作为排序方法，但是在考场上不建议使用</p><p>还可以<strong>加入多个语句进行多次的排序</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//按照成绩排序，如果第一个成绩相同就按第二个成绩排序，如果第二个成绩相同就按第三个成绩排序</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">cmp_score</span><span class="params">(Student x,Student y)</span></span>&#123;</span><br><span class="line"><span class="keyword">if</span> (x.score[<span class="number">0</span>]!=.score[<span class="number">0</span>])&#123;</span><br><span class="line"><span class="keyword">return</span> x.score[<span class="number">0</span>]&gt;y.score[<span class="number">0</span>];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span> (x.score[<span class="number">1</span>]!=.score[<span class="number">1</span>])&#123;</span><br><span class="line"><span class="keyword">return</span> x.score[<span class="number">1</span>]&gt;y.score[<span class="number">1</span>];</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> x.score[<span class="number">2</span>]&gt;y.score[<span class="number">2</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例题：<a href="https://www.lanqiao.cn/problems/1265/learning/?page=1&amp;first_category_id=1&amp;problem_id=1265&amp;sort=students_count&amp;asc=1">1.排序 - 蓝桥云课</a></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">// 请在此输入您的代码</span></span><br><span class="line">  <span class="type">int</span> size = <span class="number">0</span>;<span class="comment">//获取数组的长度</span></span><br><span class="line">  cin&gt;&gt;size;</span><br><span class="line"></span><br><span class="line">  <span class="type">int</span> num[size];</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;size;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    cin&gt;&gt;num[i];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="built_in">sort</span>(num,num+size);</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;size;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;num[i]&lt;&lt;<span class="string">&#x27; &#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  cout&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = size<span class="number">-1</span>;i&gt;=<span class="number">0</span>;i--) <span class="comment">//这里我用了取巧的方法，如果正向遍历是升序，反向遍历就是降序。就只需要排序一次</span></span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;num[i]&lt;&lt;<span class="string">&#x27; &#x27;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">    </span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>初始化列表-C++特性</strong></p><blockquote><p>常用于构造函数和实例对象创建，主要是起到简便的作用。</p></blockquote><p>如下代码所示</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Student</span>&#123;</span><br><span class="line"><span class="type">int</span> score;</span><br><span class="line">string name;</span><br><span class="line">    <span class="built_in">Student</span>()&#123;&#125;<span class="comment">//注意不可省略默认构造函数</span></span><br><span class="line"><span class="built_in">Student</span>(string n,<span class="type">int</span> s):<span class="built_in">name</span>(n),<span class="built_in">score</span>(s)&#123;&#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>初始化列表的写法是，在构造函数的括号后面加一个冒号，然后按照成员变量（参数）的格式，依次对每一个变量进行初始化，彼此之间用逗号隔开。</p><p>注意</p><ul><li>函数的参数列表绝对不能省略，像<code>Student():name(n),score(s)</code>这样的写法是不允许的。</li><li>如果在初始化完成员变量之后，还有别的事情要做，那可以把代码写在大括号里。但是，就算之后什么都不做，也必须写<br>大括号一大括号不能省略！！！</li></ul><h3 id="枚举-暴力穷举法">枚举(暴力穷举法)</h3><p>枚举就是根据提出的问题，列出该问题的所有可能的解，并在逐一列出的过程中，检验每个可能解是否是问题的真正解,如果是就采纳这个解，如果不是就继续判断下一个。<br>枚举法一般比较直观，容易理解，但由于要检查所有的可能解，因此运行效率较低。</p><p>经典枚举题目：求质数、水仙花数等。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//求质数</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n,m;</span><br><span class="line">cin&gt;&gt;n&gt;&gt;m;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j = n;j&lt;=m;j++)</span><br><span class="line">&#123;</span><br><span class="line">        <span class="keyword">if</span>(j==<span class="number">1</span>)</span><br><span class="line">        &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">        &#125;</span><br><span class="line"><span class="type">bool</span> is_prime = <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">2</span>;i&lt;j;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(j % i == <span class="number">0</span>)</span><br><span class="line">&#123;</span><br><span class="line">is_prime = fale;</span><br><span class="line">cout&lt;&lt;j&lt;&lt;<span class="string">&quot;NOT PRIME&quot;</span>&lt;&lt;endl;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(is_prime)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;j&lt;&lt;<span class="string">&quot;PRIME&quot;</span>&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//还有一种方法是遍历到根号下，也就是大概遍历到一半左右就行。</span></span><br></pre></td></tr></table></figure><h3 id="C-的STL">C++的STL</h3><h4 id="vector">vector</h4><p>动态数组.在C++中，vector是一个动态数组容器，可以存储一系列相同类型的元素。它是标准库<code>&lt;vector&gt;</code>中定义的模板类。</p><p>常用方法(具体可以看<a href="https://www.runoob.com/cplusplus/cpp-vector.html">C++ vector 容器 | 菜鸟教程</a>)</p><p><strong>函数原型：</strong></p><ul><li><p><code>push_back(ele);</code>                                         //尾部插入元素ele</p></li><li><p><code>pop_back();</code>                                                //删除最后一个元素</p></li><li><p><code>clear();</code>                                                        //删除容器中所有元素</p></li><li><p><code>size();</code>                                                           //获取vector的长度</p></li><li><p><code>insert(const_iterator pos, ele);</code>        //迭代器指向位置pos插入元素ele</p></li><li><p><code>insert(const_iterator pos, int count,ele);</code>//迭代器指向位置pos插入count个元素ele</p></li><li><p><code>erase(const_iterator pos);</code>                     //删除迭代器指向的元素</p></li><li><p><code>erase(const_iterator start, const_iterator end);</code>//删除迭代器从start到end之间的元素</p><p><strong>蓝桥杯用的最多的就是前4个</strong>，后面的遇到了再查资料。</p></li></ul><p><strong>示例：</strong></p><p><a href="https://github.com/lloyd-kai/cpp-lanqiaocup">lloyd-kai/cpp-lanqiaocup: 点击1_3文件夹-其中的Test_vector.h就是</a></p><blockquote><p>注意：<br>vector可以构造二维数组吗？可以，比如vector&lt;vector&lt;int&gt; &gt; 但要注意在int&gt; 与&gt;   之间留一个空格，否则有些老编译器无法通过。</p></blockquote><p>例题：蓝桥杯问题编号3226</p><h4 id="set">set</h4><p>使用前提：引入头文件<code>#include &lt;set&gt;</code>.</p><p>set是一种容器，用于存储一组唯的元素，并按照一定的排序规则进行排序。st中的元素是按照升序排序的，默认情况下，它使用元素的比较运算符(&lt;)来进行排序(也就是从小到大排序)。</p><p>定义：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">class</span> <span class="title class_">Key</span>,<span class="keyword">class</span> <span class="title class_">Compare</span> = less&lt;Key&gt;,<span class="keyword">class</span> Allocator = allocator&lt;Key&gt;&gt;</span><br><span class="line"><span class="keyword">class</span> set;</span><br></pre></td></tr></table></figure><ul><li>Key:表示存储在set中的元素的类型。</li><li>Compare:表示元素之间的比较函数对象的类型，默认为less,即按照元素的值进行比较。</li><li>Allocator:表示用于分配内存的分配器类型，默认为allocator.</li></ul><p>sett的内部实现使用了红黑树（一种自平衡的二叉搜索树）来存储元素，并保持元素的有序性。这使得在set中插入、删除和查找元素的时间复杂度都是对数时间.<br><strong>set中的元素是唯一的，即不允许重复的元素存在。当插入一个重复的元素时，set会自动忽略该元素</strong>。</p><p><strong>multiset</strong></p><p>multiset:是一种容器(多重集合)，它与set类似，用于存储一组元素，并按照一定的排序规则进行排序。不同之处在于，multiset容器允许存储重复的元素。</p><p><strong>unordered_set</strong></p><p>无序集合：是一种容器，用于存储一组唯一的元素，并且没有特定的顺序。unordered_set容器使用哈希表来实现元素的存储和访问，因此元素的插入、删除和查找的时间复杂度都是常数时间，即O(1)。同样因为哈希的不稳定性在考试中很少用，但是在leetcode中经常用。</p><p>使用示例：</p><p><a href="https://github.com/lloyd-kai/cpp-lanqiaocup">lloyd-kai/cpp-lanqiaocup: 点击1_3文件夹-其中的Test_set.h就是</a></p><h4 id="string">string</h4><p>字符串(C++)</p><p>字符串的基本使用</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 声明并初始化字符串</span></span><br><span class="line">    std::string greeting = <span class="string">&quot;Hello, World!&quot;</span>;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Greeting: &quot;</span> &lt;&lt; greeting &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用 size() 获取字符串长度</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Length of the greeting: &quot;</span> &lt;&lt; greeting.<span class="built_in">size</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用 empty() 检查字符串是否为空</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Is the greeting empty? &quot;</span> &lt;&lt; (greeting.<span class="built_in">empty</span>() ? <span class="string">&quot;Yes&quot;</span> : <span class="string">&quot;No&quot;</span>) &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用 operator[] 访问特定位置的字符</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Character at position 7: &quot;</span> &lt;&lt; greeting[<span class="number">7</span>] &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用 substr() 获取子字符串</span></span><br><span class="line">    std::string sub = greeting.<span class="built_in">substr</span>(<span class="number">7</span>, <span class="number">5</span>);</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Substring from position 7 with length 5: &quot;</span> &lt;&lt; sub &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用 find() 查找子字符串</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Position of &#x27;World&#x27; in the greeting: &quot;</span> &lt;&lt; greeting.<span class="built_in">find</span>(<span class="string">&quot;World&quot;</span>) &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用 replace() 替换字符串中的部分内容</span></span><br><span class="line">    <span class="comment">// 替换 &#x27;World&#x27; 为 &#x27;C++&#x27;</span></span><br><span class="line">    std::string modified = greeting;</span><br><span class="line">    std::string::size_type pos = modified.<span class="built_in">find</span>(<span class="string">&quot;World&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (pos != std::string::npos) &#123;</span><br><span class="line">        modified.<span class="built_in">replace</span>(pos, <span class="number">5</span>, <span class="string">&quot;C++&quot;</span>); <span class="comment">// 从位置 pos 开始，替换 5 个字符为 &quot;C++&quot;</span></span><br><span class="line">    &#125;</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Modified greeting: &quot;</span> &lt;&lt; modified &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>常用的其他函数</p><ol><li>getline(cin,s)；读取一行字符串。</li><li>c_str():将参数转化为C风格字符串(const char *) ，如果想要使用printf打印string，就需要用c_str将其转化为C语言的字符串。</li></ol><h4 id="queue">queue</h4><p>queue是一种先进先出(FIFO)的数据结构。queue提供了一组函数来操作和访问元素，但它的功能相对较简单。用的多的是<code>priority_queue</code>(也被称为<strong>大顶堆</strong>)</p><p>priority_queue.与普通队列不同，priority_queue中的元素是按照一定的优先级进行排序的。默认情况下，priority queue:<strong>按照元素的值从大到小进行排序</strong>。当然可以通过重载运算符或者是自定义比较函数修改其比较函数</p><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//自定义比较函数</span></span><br><span class="line"><span class="comment">//方法1 重载运算符</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Compare</span>&#123;</span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">operator</span><span class="params">()</span><span class="params">(<span class="type">int</span> a,<span class="type">int</span> b)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//自定义的比较函数 按照逆序排列</span></span><br><span class="line"><span class="keyword">return</span> a&gt;b; </span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用自定义函数的方法</span></span><br><span class="line"><span class="comment">//在需要的地方写 priority_queue&lt;int,vector&lt;int&gt;,Compare&gt;pq;</span></span><br><span class="line"><span class="comment">//注意两种自定义函数方法对应的初始化队列的格式是不一样的 </span></span><br><span class="line">&#125;; </span><br><span class="line"></span><br><span class="line"><span class="comment">//方法2 自定义比较函数 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_Compare</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//自定义比较函数，注意这里使用auto简化函数类型的书写</span></span><br><span class="line"><span class="keyword">auto</span> compare = [](<span class="type">int</span> a,<span class="type">int</span> b)&#123;</span><br><span class="line"><span class="comment">//自定义比较函数</span></span><br><span class="line"><span class="keyword">return</span> a&gt;b; </span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="comment">//使用自定义比较函数的方法 </span></span><br><span class="line">priority_queue&lt;<span class="type">int</span>,vector&lt;<span class="type">int</span>&gt;,<span class="keyword">decltype</span>(compare)&gt;<span class="built_in">pq</span>(compare);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果只是想将大顶堆变为小顶堆(从小到大排序)，可以直接用greater&lt;T&gt; 如<code>priority_queue&lt;int,vector&lt;int&gt;,greater&lt;int&gt;&gt; pq;</code></p><p><strong>deque</strong></p><p>deque（<strong>双端队列</strong>）是一种容器，它允许在两端进行高效的插入和删除操作。deque是由一系列连续的存储块（缓沛区）组成的，每个存储块都存储了多个元素。这使得deque能够在两端进行快速的插入和删除操作，而不需要移动其他元素。</p><p><strong>队列例题</strong></p><p><a href="https://www.lanqiao.cn/problems/1113/learning/?page=1&amp;first_category_id=1&amp;problem_id=1113">1.CLZ银行问题 问题编号1113</a></p><p>难点在于对输入字符串的处理和队列的函数使用，注意队列的遍历一般使用边用头(front)输出边用(pop)出队。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;queue&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//加快cout与cin的速度</span></span><br><span class="line">  ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line">  <span class="comment">//初始化次数</span></span><br><span class="line">  <span class="type">int</span> count = <span class="number">0</span>;</span><br><span class="line">  cin&gt;&gt;count;</span><br><span class="line">  <span class="comment">//初始化队列</span></span><br><span class="line">  queue&lt;string&gt;V,N;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//开始执行相关操作</span></span><br><span class="line">  <span class="keyword">while</span>(count--)</span><br><span class="line">  &#123;</span><br><span class="line">    string op;</span><br><span class="line">    cin&gt;&gt;op;</span><br><span class="line">    <span class="keyword">if</span>(op == <span class="string">&quot;IN&quot;</span>)</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">//执行队列添加元素</span></span><br><span class="line">      string name,q;</span><br><span class="line">      cin&gt;&gt;name&gt;&gt;q;</span><br><span class="line">      <span class="keyword">if</span>(q == <span class="string">&quot;V&quot;</span>)</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="comment">//VIP队列添加元素</span></span><br><span class="line">        V.<span class="built_in">push</span>(name);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">else</span></span><br><span class="line">      &#123;</span><br><span class="line">        N.<span class="built_in">push</span>(name);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">//出队操作</span></span><br><span class="line">      string q;</span><br><span class="line">      cin&gt;&gt;q;</span><br><span class="line">      <span class="keyword">if</span>(q == <span class="string">&quot;V&quot;</span>)</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="comment">//VIP队列添加元素</span></span><br><span class="line">        V.<span class="built_in">pop</span>();</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">else</span></span><br><span class="line">      &#123;</span><br><span class="line">        N.<span class="built_in">pop</span>();</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//输出队列中的元素</span></span><br><span class="line">  <span class="keyword">while</span>(V.<span class="built_in">size</span>())</span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;V.<span class="built_in">front</span>()&lt;&lt;endl;</span><br><span class="line">    V.<span class="built_in">pop</span>();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">while</span>(N.<span class="built_in">size</span>())</span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;N.<span class="built_in">front</span>()&lt;&lt;endl;</span><br><span class="line">    N.<span class="built_in">pop</span>();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="https://www.lanqiao.cn/problems/741/learning/?page=1&amp;first_category_id=1&amp;problem_id=741">1.合并果子 问题编号741</a></p><p>难点：1. 数据的类型要使用long long 而不是使用int 2. 这里要使用小顶堆+队列的出队入队操作。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;queue&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//提高速度</span></span><br><span class="line">  ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">  <span class="comment">//初始化堆数</span></span><br><span class="line">  <span class="type">int</span> count = <span class="number">0</span>;</span><br><span class="line">  cin&gt;&gt;count;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//初始化优先级队列,小顶堆</span></span><br><span class="line">  priority_queue&lt;ll,vector&lt;ll&gt;,greater&lt;<span class="type">int</span>&gt;&gt; pile;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;count;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    ll tem = <span class="number">0</span>;</span><br><span class="line">    cin&gt;&gt;tem;</span><br><span class="line">    pile.<span class="built_in">push</span>(tem);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  ll num = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">while</span>(pile.<span class="built_in">size</span>()&gt;=<span class="number">2</span>)</span><br><span class="line">  &#123;</span><br><span class="line">    ll x = pile.<span class="built_in">top</span>();</span><br><span class="line">    pile.<span class="built_in">pop</span>();</span><br><span class="line">    ll y = pile.<span class="built_in">top</span>();</span><br><span class="line">    pile.<span class="built_in">pop</span>();</span><br><span class="line">    num+=x+y;</span><br><span class="line">    pile.<span class="built_in">push</span>(x+y);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  cout&lt;&lt;num;</span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="https://www.lanqiao.cn/problems/1624/learning/?page=1&amp;first_category_id=1&amp;problem_id=1624">1.小蓝吃糖果 问题编号1624</a></p><p>难点在于总结出可行方案的充要条件是<strong>所有糖果数量之和-数量最高的一种糖果的数量&gt;=数量最高的一种糖果的数量-1</strong>，也就是说，除开数量最多的糖果，其他的糖果要能填满(&gt;=)数量最高的一种糖果形成的“间隔”(也就是先吃数量最高的糖果，然后吃其他种类的)。<br>还有一个小细节就是糖果之和会很大，需要使用long long避免溢出.</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;queue&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">// 请在此输入您的代码</span></span><br><span class="line">  ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line">  <span class="comment">//初始化</span></span><br><span class="line">  <span class="type">int</span> num = <span class="number">0</span>;</span><br><span class="line">  cin&gt;&gt;num;</span><br><span class="line"></span><br><span class="line">  <span class="type">long</span> <span class="type">long</span> sum = <span class="number">0</span>;</span><br><span class="line">  priority_queue&lt;<span class="type">int</span>&gt; v;</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;num;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="type">int</span> temp = <span class="number">0</span>;</span><br><span class="line">    cin&gt;&gt;temp;</span><br><span class="line">    v.<span class="built_in">push</span>(temp);</span><br><span class="line">    sum+=temp;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span>(sum-v.<span class="built_in">top</span>()&gt;=v.<span class="built_in">top</span>()<span class="number">-1</span>)</span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;Yes&quot;</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">else</span></span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt;<span class="string">&quot;No&quot;</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="迭代器">迭代器</h4><p>C++通过迭代器可以访问集合中的每个元素，迭代器就好像一根手指指向set中的某个元素(<strong>迭代器不仅仅可以在set上使用，还可以在其他的STL中使用</strong>)<br>要改变它指向的元素。通过*(这是解引用运算符，不是乘号的意思)操作可以获取迭代器指向的元素。通过<code>+</code>操作让迭代器指向下一个元素，同理-操作让迭代器指向上一个元素。<br>迭代器的写法比较固定，<code>set&lt;T&gt;::iterator it</code>就定义了一个指向<code>set&lt;T&gt;</code>这种集合的迭代器it,T是任意的数据类型。其中：iterator是固定的写法。begin函数返回容器中起始元素的迭代器，end函数返回容器的尾后迭代器。</p><p>用法如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 创建一个 vector 容器并初始化</span></span><br><span class="line">    std::vector&lt;<span class="type">int</span>&gt; vec = &#123;<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>&#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 使用迭代器遍历 vector</span></span><br><span class="line">    <span class="keyword">for</span> (std::vector&lt;<span class="type">int</span>&gt;::iterator it = vec.<span class="built_in">begin</span>(); it != vec.<span class="built_in">end</span>(); ++it) &#123;</span><br><span class="line">        std::cout &lt;&lt; *it &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    std::cout &lt;&lt; std::endl;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="重载运算符">重载运算符</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Node</span>&#123;</span><br><span class="line"><span class="type">int</span> x,y;</span><br><span class="line"><span class="type">bool</span> <span class="keyword">operator</span>&lt;(<span class="type">const</span> Node &amp; rhs)<span class="type">const</span> &#123;</span><br><span class="line"><span class="keyword">if</span>(x == a.x)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> y&lt;rhs.y;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span> x&lt;rhs.x;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>operator&lt;</code>表示我们要重载运算符<code>&lt;</code>，可以看成是一个函数名。<code>rhs</code>是“right hand side”的简称，有右操作数的意思，这里我<br>们定义为一个const引用。因为该运算符重载定义在结构体内部，左操作数就当前调用<code>operator&lt;</code>的对象。<br>特别要注意，不要漏掉最后的const。const函数表示不能对其数据成员进行修改操作，并且const对象不能调用非const成员<br>函数，只允许调用const成员函数。<br>上面重载规定了排序方式为，优先按照x从小到大排序，如果x相同，那么再按照y从小到大排序。经过了<code>&lt;</code>运算符重载的结<br>构体，我们就可以比较两个Node对象的大小了，因此可以直接储存在set中了。</p><h4 id="map">map</h4><p>映射：是指两个集合之间的元素的相互对应关系。通俗地说，就是一个元素对应另外一个元素。比如Tom-&gt;1,Mary-&gt;2.我们称其中的姓名集合({“Tom”,“Mary”}为关键字集合key,班级集合({1,2}为值集合(value),在C++中常用的映射有map。</p><p>map是一种关联容器，用于存储一组键值对(key-value pairs),其中<strong>每个键(key)都是唯一的</strong>。map容器根据键来自动进行排序，并且可以通过键茯速查找对应的值。map容器使用<strong>红黑树</strong>(Red-Black Tree) 数据结构来实现，具有较快的插入、删除和查找</p><p><strong>构造一个映射</strong><br>现在我们来构造一个映射。<br>在C++中，我们构造一个map的语句为：<code>map&lt;T1,2&gt;m</code>;。这样我们定义了一个名为m的从T1类型到T2类型的映射。初始的时候m是空映射。比如<code>map&lt;string,int&gt;m</code>构建了一个字符串到整数的映射，这样我们可以把一个字符串和一个整数关联起来。</p><p><strong>插入一对映射</strong><br>在C++中通过insert函数向集合中插入一个新的映射，参数是一个pair。pair是一个标准库类型，定义在头文件utility中。可以看成是有两个成员变量first和second的结构体，并且重载了<code>&lt;</code>运算符(先比较first大小，如果一样再比较second)。当我们创建一个pair时，必须提供两个类型。<br>我们可以像这样定义一个保存string和int的pair</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pair&lt;string,<span class="type">int</span>&gt;p;</span><br></pre></td></tr></table></figure><p><code>make_pair(v1,v2)</code>函数返回由v1和v2初始化的pair,类型可以从v1和v2的类型推断出来。<br>我们向映射中加入新映射对的时候就是通过插入pair来实现的。如果插入的key之前已经存在了，将不会用插入的新的value替代原来的value,也就是这次插入是无效的。</p><p><strong>访问映射</strong><br>在C++中访问映射和数组一样，直接用<code>[]</code>就能访问。比如<code>dict[&quot;Tom&quot;]</code>就可以获取&quot;Tom&quot;的班级了。而这里有一个比较神奇的地方，如果没有对&quot;Tom&quot;做过映射的话，此时你访问<code>dict[&quot;Tom&quot;]</code>,系统将会自动为&quot;Tom&quot;生成一个映射，其value为对应类型的默认值(比如int的默认值是0,string的默认值是空字符串)。并且我们可以之后再给映射赋予新的值，比如<code>dict[&quot;Tom&quot;]=3,</code>这样为我们提供了另一种方便的插入手段。实际上，我们常常通过下标访问的方式来插入映射，而不是通过用insert插入一个pair来实现。</p><p><strong>判断关键字是否存在</strong></p><p>在C++中，如果你想知道某个关键字是否被映射过，你可以直接用<code>count</code>函数。如果关键字存在，返回1，否则会返回0。<strong>示例如下</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;map&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 创建一个 map 容器，存储员工的姓名和年龄</span></span><br><span class="line">    std::map&lt;std::string, <span class="type">int</span>&gt; employees;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 插入员工信息</span></span><br><span class="line">    employees[<span class="string">&quot;Alice&quot;</span>] = <span class="number">30</span>;</span><br><span class="line">    employees[<span class="string">&quot;Bob&quot;</span>] = <span class="number">25</span>;</span><br><span class="line">    employees[<span class="string">&quot;Charlie&quot;</span>] = <span class="number">35</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//查找员工是否存在</span></span><br><span class="line">    <span class="keyword">if</span>(employees.<span class="built_in">count</span>(<span class="string">&quot;Alice&quot;</span>))</span><br><span class="line">    &#123;</span><br><span class="line">        cout&lt;&lt;<span class="string">&quot;Alice is a employees&quot;</span>&lt;&lt;endl;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        cout&lt;&lt;<span class="string">&quot;Alice is not a employees&quot;</span>&lt;&lt;endl;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//这里的代码接下文</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>遍历映射</strong></p><p>map的迭代器的定义和set差不多，<code>map&lt;T1,T2&gt;::iterator it</code>就定义了一个迭代器，其中T1、T2分别是key和value的类型。<br>C++通过迭代器可以访问集合中的每个元素。这里迭代器指向的元素是一个pair,有<strong>first</strong>和<strong>second</strong>两个成员变量，分别代<br>表一个映射的key和value.我们用<code>-&gt;</code>运算符来获取值，<code>it-&gt;first</code>和<code>(*it).first</code>的效果是一样的，就是获取迭代器it指向的pair里first成员的值。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//这里的代码接上文</span></span><br><span class="line"><span class="comment">// 遍历 map 并打印员工信息</span></span><br><span class="line">   <span class="keyword">for</span> (std::map&lt;std::string, <span class="type">int</span>&gt;::iterator it = employees.<span class="built_in">begin</span>(); it != employees.<span class="built_in">end</span>(); ++it) &#123;</span><br><span class="line">       std::cout &lt;&lt; it-&gt;first &lt;&lt; <span class="string">&quot; is &quot;</span> &lt;&lt; it-&gt;second &lt;&lt; <span class="string">&quot; years old.&quot;</span> &lt;&lt; std::endl;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure><p>注意：C++中遍历map是按照关键字从小到大遍历的</p><p>map里面可以套用set或者是map，主要是用于处理键值对重复的问题，或者也可以使用<code>multimap</code>，此容器可允许存储多个具有相同键的键值对。</p><p><strong>扩展</strong>：unordered_map</p><p>也是map的一种，不同的是unordered_map不会根据键的顺序进行排序，而是使用<strong>哈希函数</strong>将键映射到存储桶中，所以在增删查改方面速度较快，但是元素的顺序无法保证，且时间复杂度不稳定，在leetcode中有些题目用的较多。</p><p>例题</p><p><a href="https://www.lanqiao.cn/problems/1531/learning/?page=1&amp;first_category_id=1&amp;problem_id=1531">1.快递分拣  问题编号 1531</a></p><p>难点在于直接用map的键访问其值是困难的，那么就可以将所有的值看作是一个“集合”，也就是vector类型，这样就巧妙解决了访问的问题。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line">map&lt;string,vector&lt;string&gt;&gt;mp;</span><br><span class="line"><span class="comment">//一个城市对应多个快递单号，这里最好使用vector容器，用map键访问会很麻烦</span></span><br><span class="line">vector&lt;string&gt;citys;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//施法前摇</span></span><br><span class="line">  ios::<span class="built_in">sync_with_stdio</span>(<span class="number">0</span>),cin.<span class="built_in">tie</span>(<span class="number">0</span>),cout.<span class="built_in">tie</span>(<span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">  <span class="type">int</span> num = <span class="number">0</span>;</span><br><span class="line">  cin&gt;&gt;num;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;num;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    string a,b;</span><br><span class="line">    cin&gt;&gt;a&gt;&gt;b;</span><br><span class="line">    mp[b].<span class="built_in">push_back</span>(a);</span><br><span class="line">    <span class="keyword">if</span>(mp[b].<span class="built_in">size</span>() == <span class="number">1</span>)</span><br><span class="line">    &#123;</span><br><span class="line">      citys.<span class="built_in">push_back</span>(b);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;city : citys)</span><br><span class="line">  &#123;</span><br><span class="line">    cout&lt;&lt; city &lt;&lt;<span class="string">&#x27; &#x27;</span>&lt;&lt;mp[city].<span class="built_in">size</span>()&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">const</span> <span class="keyword">auto</span> &amp;i:mp[city])</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="comment">//输出其快递编号</span></span><br><span class="line">      cout &lt;&lt; i &lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="stack">stack</h4><p>栈，是一种满足一定约束的线性数据结构。其约束是：只允许在栈的一端插入或删除元素，这一端被称为栈顶；相对地，我们<br>把另一端称为栈底。</p><p>标准库里面的stack在头文件<code>&lt;stack&gt;</code>里面，它的定义和map、set、vector都大同小异，如果你对前面的标准库已经使用得很熟练了，那么对于stack的使用你也会一目了然。<code>stack&lt;T&gt;s</code>定义了一个储存T类型数据的栈s.标准库的栈除了支持push(),pop()等基本操作以外，还支持top()来获取栈顶元素、empty()判断栈是否为空、size()计算栈中元素的个数。</p><p><strong>使用示例</strong> 常用的几乎就在以下示例中</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stack&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    std::stack&lt;<span class="type">int</span>&gt; s;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 向栈中添加元素</span></span><br><span class="line">    s.<span class="built_in">push</span>(<span class="number">10</span>);</span><br><span class="line">    s.<span class="built_in">push</span>(<span class="number">20</span>);</span><br><span class="line">    s.<span class="built_in">push</span>(<span class="number">30</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 打印栈顶元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Top element is: &quot;</span> &lt;&lt; s.<span class="built_in">top</span>() &lt;&lt; std::endl; <span class="comment">// 输出: Top element is: 30</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 移除栈顶元素</span></span><br><span class="line">    s.<span class="built_in">pop</span>();</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;After popping, top element is: &quot;</span> &lt;&lt; s.<span class="built_in">top</span>() &lt;&lt; std::endl; <span class="comment">// 输出: After popping, top element is: 20</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 检查栈是否为空</span></span><br><span class="line">    <span class="keyword">if</span> (!s.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;Stack is not empty.&quot;</span> &lt;&lt; std::endl; <span class="comment">// 输出: Stack is not empty.</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 打印栈的大小</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Size of stack: &quot;</span> &lt;&lt; s.<span class="built_in">size</span>() &lt;&lt; std::endl; <span class="comment">// 输出: Size of stack: 2</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 继续移除元素</span></span><br><span class="line">    s.<span class="built_in">pop</span>();</span><br><span class="line">    s.<span class="built_in">pop</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 检查栈是否为空</span></span><br><span class="line">    <span class="keyword">if</span> (s.<span class="built_in">empty</span>()) &#123;</span><br><span class="line">        std::cout &lt;&lt; <span class="string">&quot;Stack is empty.&quot;</span> &lt;&lt; std::endl; <span class="comment">// 输出: Stack is empty.</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><a href="https://www.lanqiao.cn/problems/2490/learning/?page=1&amp;first_category_id=1&amp;problem_id=2490">1.小蓝的括号串1 问题编号2490</a></p><p>读者可以尝试使用栈解决问题。</p><h4 id="list">list</h4><p>lis的使用频率不高，在做题时极少遇到需要使用lis的情景(因为<strong>一般用数组实现链表</strong>)。list是一种双向链表容器，它是标准模板库（STL）提供的一种序列容器。list容器以<strong>节点</strong>(node)的形式存储元素，并使用指针将这些节点链接在一起，形成一个链表结构。</p><p>list容器模板接受两个参数：1.T：指定容器中存储的元素类型 2.Allocator(可选)：指定用于分配内存的分配器类型，默认为<code>std:allocator&lt;T&gt;</code></p><p>list容器的特点包括：</p><ul><li>双向性：每个节点都包含指向前一个节点和后一个节点的指针，因此可以在常数时间内在链表中的任意位置进行插入、删除和访问操作。</li><li>动态大小：链表的大小可以根据需要动态扩展或收缩，不需要预先指定容器的大小。</li><li>不连续存储：链表中的节点可以在内存中的任意位置分布，不要求连续存储，因此插入和删除操作不会导致元素的移动。</li></ul><p>list容器提供了一系列成员函数和迭代器来操作和访问链表中的元素，包括增加,删除、访问、反转等操作。可以使用迭代器来遍历链表中的元素。</p><p>需要注意的是，由于s是双向链表，因此插入和删除操作的时间复杂度是常量时间O(1),但访问和查找操作的时间复杂度是线性时间On),其中n是链表的大小。因此，如果需要频繁进行随机访问操作，可能更适合使用支持随机访问的容器，如vector或deque。</p><p>示例(来源：<a href="https://www.runoob.com/cplusplus/cpp-libs-list.html">C++ 容器类  | 菜鸟教程</a>)  具体常用的函数里面也有示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;list&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 创建一个整数类型的列表</span></span><br><span class="line">    std::list&lt;<span class="type">int</span>&gt; numbers;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 向列表中添加元素</span></span><br><span class="line">    numbers.<span class="built_in">push_back</span>(<span class="number">10</span>);</span><br><span class="line">    numbers.<span class="built_in">push_back</span>(<span class="number">20</span>);</span><br><span class="line">    numbers.<span class="built_in">push_back</span>(<span class="number">30</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 访问并打印列表的第一个元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;First element: &quot;</span> &lt;&lt; numbers.<span class="built_in">front</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 访问并打印列表的最后一个元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;Last element: &quot;</span> &lt;&lt; numbers.<span class="built_in">back</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 遍历列表并打印所有元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;List elements: &quot;</span>;</span><br><span class="line">    <span class="keyword">for</span> (std::list&lt;<span class="type">int</span>&gt;::iterator it = numbers.<span class="built_in">begin</span>(); it != numbers.<span class="built_in">end</span>(); ++it) &#123;</span><br><span class="line">        std::cout &lt;&lt; *it &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    std::cout &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 删除列表中的最后一个元素</span></span><br><span class="line">    numbers.<span class="built_in">pop_back</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 再次遍历列表并打印所有元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;List elements after removing the last element: &quot;</span>;</span><br><span class="line">    <span class="keyword">for</span> (std::list&lt;<span class="type">int</span>&gt;::iterator it = numbers.<span class="built_in">begin</span>(); it != numbers.<span class="built_in">end</span>(); ++it) &#123;</span><br><span class="line">        std::cout &lt;&lt; *it &lt;&lt; <span class="string">&quot; &quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    std::cout &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="pair">pair</h4><p>在C+中，pair是一个模板类，用于表示一对值的组合。它位于<code>&lt;utility&gt;</code>头文件中<br>pair类模板有两个模板参数，T1和T2,分别表示第一个值和第二个值的类型<br>pair类有两个成员变量，first和second,分别表示第一个值和第二个值。<br>pair类还有一些成员函数和特性，例如默认构造函数、带参数的构造函数、比较运算符重载等。使用pair类，你可以方便地将两个值组合在一起,并进行传递、存储和操作。pair是可以嵌套的</p><p>pair自带的排序规则是按照<strong>first成员进行升序排序</strong>。如果first成员相等，则按照second成员进行升序排序。这意味着当你使用标准库中的排序算法(如std:sort)对包含pair对象的容器进行排序时,会根据pair对象的first)成员进行排序。</p><p>示例见我的github仓库</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//这里是部分展示</span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> once </span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;utility&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="comment">//定义一个结构体，表示一个人的信息</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Person</span></span><br><span class="line">&#123;</span><br><span class="line">string name;</span><br><span class="line"><span class="type">int</span> age;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_pair</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//创建一个存储Person对象的vector容器</span></span><br><span class="line">vector&lt;Person&gt; people;</span><br><span class="line"></span><br><span class="line"><span class="comment">//添加一些Person对象到vector中</span></span><br><span class="line">people.<span class="built_in">push_back</span>(&#123;<span class="string">&quot;Alice&quot;</span>,<span class="number">25</span>&#125;);</span><br><span class="line">people.<span class="built_in">push_back</span>(&#123;<span class="string">&quot;Bob&quot;</span>,<span class="number">30</span>&#125;);</span><br><span class="line">people.<span class="built_in">push_back</span>(&#123;<span class="string">&quot;Charlie&quot;</span>,<span class="number">20</span>&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//创建一个存储pair的vector</span></span><br><span class="line">vector&lt;pair&lt;Person,<span class="type">int</span>&gt;&gt;scores;</span><br><span class="line"></span><br><span class="line"><span class="comment">//添加一些元素</span></span><br><span class="line">scores.<span class="built_in">push_back</span>(&#123;people[<span class="number">0</span>],<span class="number">90</span>&#125;);</span><br><span class="line">scores.<span class="built_in">push_back</span>(&#123;people[<span class="number">1</span>],<span class="number">85</span>&#125;);</span><br><span class="line">scores.<span class="built_in">push_back</span>(&#123;people[<span class="number">2</span>],<span class="number">95</span>&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">//遍历，打印姓名年龄和评分</span></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">auto</span> it:scores) &#123;</span><br><span class="line">cout&lt;&lt;<span class="string">&quot;Name is &quot;</span>&lt;&lt;it.first.name&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">cout&lt;&lt;<span class="string">&quot;Age is &quot;</span>&lt;&lt;it.first.age&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">cout&lt;&lt;<span class="string">&quot;Score is &quot;</span>&lt;&lt;it.second&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>注意<strong>C++11特性里面包括auto自动类型推导+遍历</strong>，在考试的时候就不需要写冗长的迭代器了。</p><h3 id="递归">递归</h3><p>递归是计算机编程中应用最广泛的一个技巧，也是比较难理解的一个技巧，所以我们打算花大量的时间来理解递归。所谓递归，就是函数调用函数自身，一个函数在其定义中有直接或者间接调用自身都叫递归。而递归一般都用来解决有重复子问题的问题。我们先来理解直接递归，间接递归非常复杂，用的比较少。下面通过求解！(！代表阶乘)的问题来理解直接递归。我们知道n!=n×(n-1)！，所以我们很容易写下下面的代码。如果仅仅写一个递归式子还是很简单的，但是<strong>递归的一个难点</strong>就是——<strong>边界条件</strong>。所谓边界条件，就是在什么情况下，函数不应该再继续调用自身。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//以下就是常见的递归格式</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">factorial</span><span class="params">(<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(n == <span class="number">1</span>)<span class="comment">//递归边界，也就是递归终止条件</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">return</span> n*<span class="built_in">factorial</span>(n<span class="number">-1</span>);<span class="comment">//将大问题分解为子问题  使用递归解决子问题</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>经典题型1：</strong> 汉诺塔</p><p>汉诺问题看似复杂，其实不管是多少，都可以归纳为三个步骤：1. 把n-1个盘子从A移动到B,此时A上只剩下最下面的一个盘子。2. 直接把最后一个盘子从A移动到C。3.把B上的n-1个盘子移动到C上。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stack&gt;</span> </span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line">stack&lt;<span class="type">int</span>&gt; S[<span class="number">3</span>];<span class="comment">//汉诺塔的杆子数 </span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">move</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y)</span><span class="comment">//盘子移动函数 </span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> temp = S[x].<span class="built_in">top</span>(); </span><br><span class="line">S[x].<span class="built_in">pop</span>();</span><br><span class="line">S[y].<span class="built_in">puish</span>(temp);</span><br><span class="line">cout&lt;&lt;x&lt;&lt;<span class="string">&quot;--&gt;&quot;</span>&lt;&lt;y&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">hanoi</span><span class="params">(<span class="type">int</span> A,<span class="type">int</span> B,<span class="type">int</span> C,<span class="type">int</span> n)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(n == <span class="number">1</span>)<span class="comment">//如果A杆只有一个盘子时 </span></span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">move</span>(A,C);<span class="comment">//将A杆的盘子直接移动到C </span></span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">hanoi</span>(A,C,B,n<span class="number">-1</span>); <span class="comment">//将A杆盘子经由C移动到B，并减少A杆的盘子数 </span></span><br><span class="line"><span class="built_in">move</span>(A,C);</span><br><span class="line"><span class="built_in">hanoi</span>(B,A,C,n<span class="number">-1</span>);<span class="comment">//将剩下B杆的盘子经由A移动到C，直到所有的盘子都移动到C。 </span></span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n; </span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = n;i&gt;=<span class="number">1</span>;i--)<span class="comment">//演示汉诺塔 </span></span><br><span class="line">&#123;</span><br><span class="line">S[<span class="number">0</span>].<span class="built_in">push</span>(i);</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">hanoi</span>(<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,n);</span><br><span class="line"><span class="keyword">while</span>(!S[<span class="number">2</span>].<span class="built_in">empty</span>())</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;S[<span class="number">2</span>].<span class="built_in">top</span>()&lt;&lt;<span class="string">&quot; &quot;</span>;</span><br><span class="line">S[<span class="number">2</span>].<span class="built_in">pop</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="深度优先搜索-DFS">深度优先搜索(DFS)</h3><p>深度优先搜索按照深度优先的方式进行搜索，通俗点说就是“一条路走到黑”。注意，这里的“搜索”不是指的我们平时在文件中或者在网络上查找某些信息，搜索是一种穷举的方式，把所有可行的方案都列出来，不断去尝试，直到找到问题的解。深度优先搜索和递归的区别是：深度优先搜索是一种算法，注重的是思想；而递归是一种基于编程语言的实现方式。<strong>深度优先搜索可以用递归实现，并且两者之间有很多相似之处</strong>，也就是说递归是我们用计算机编程语言来实现深度优先搜索这个算法的手段。</p><p>以走迷宫为例，首先找到起点S,走到每个点时，按照左、下、右、上的顺序尝试。每走到下一个点以后，我们把这个点当做起点S,继续按顺序尝试。如果某个点上下左右四个方向都尝试过，便回到走到这个点之前的点，这一步我们称之为回溯。继续尝试其他方向。直到所有点都尝试过上下左右四个方向。这就好比你自己去走这个迷宫，你也要一个方向一个方向的尝试着走，如果这条路不行，就回头，尝试下一条路，ds的思想和我们直观的想法很类似。只不过，接下来我们需要用程序来完成这个过程。</p><p><strong>抽象深度优先搜索</strong></p><p>前面用到的fs算法都是比较容易想象出搜索过程的，接下来我们看一些不那么容易想象搜索过程的fs过程，这些问题我们称为抽象形式的dfs.<br>来看一个非常简单的问题：给定n个整数，要求选出K个数，使得选出来的K个数的和为sum。</p><p>我们在搜索的过程中，用S来记录当前选择的数值总和，k来记录选择的数的个数，deep表示当前正在枚举第几个数是否选择。在第一层dfs的时候，我们可以枚举是否选第一个数，如果选第一个数则让S加上第一个数且k加一，dfs进入到下一层；否则fs直接进入到下一层。当然，这里我们还需要借助全局变量、参数或修改数组中元素的值等方式来标识出当前的层数，为了减少篇幅，在下文中就直接忽略掉了。在第二层，对第二个数做同样的处理，dfs的过程中记录已经选取的数的个数，如果已经选取了k个数，判断S值是否等于su.对于每一层，我们都有两个选择一选和不选。不同的选择，都会使得搜索进入完全不同的分支继续搜索。<strong>和搜索树有很大的关系</strong>。</p><p>如果对搜索树和状态有很好的理解，对后面的广度优先搜索和动态规划的学习都有很大的帮助。前面说过，dfs看起来是运行在图上的搜索算法，而前一节给大家展示的dfs过程，我们没有看到图的存在，这就是抽象形式的dfs的特点。我们可以根据搜索状态构建一张抽象的图，图上的一个顶点就是一个状态，而图上的边就是状态之间的转移关系（进一步搜索或回溯）。虽然s是在这张抽象的图上进行的，但我们不必把这张图真正地建立出来。</p><p>我们可以认为，一次dfs实际上就是在搜索树上完成了一次深度优先搜索。而在上节中的搜索树里的每一个状态，记录了两个值一和值和个数。对于每个数，我们都有两个选择一选和不选。不同的选择，都会使得搜索进入完全不同的分支继续搜索。而每个状态对应的子树，都是这个状态通过搜索可能达到的状态。</p><p><strong>给定n个整数，要求选出K个数，使得选出来的K个数的和为sum。</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> n,k,sum,ans;</span><br><span class="line"><span class="type">int</span> a[<span class="number">40</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> cnt,<span class="type">int</span> s)</span> <span class="comment">//cnt为数的个数</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(i == n) <span class="comment">//i是层数</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(cnt == k &amp;&amp; s == sum)  <span class="comment">//s是数的和</span></span><br><span class="line">&#123;</span><br><span class="line">ans++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">dfs</span>(i<span class="number">+1</span>,cnt,s);</span><br><span class="line"><span class="built_in">dfs</span>(i<span class="number">+1</span>,cnt<span class="number">+1</span>,s+a[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//输入数据</span></span><br><span class="line">cion&gt;&gt;n&gt;&gt;k&gt;&gt;sum;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line">ans = <span class="number">0</span>;</span><br><span class="line"><span class="built_in">dfs</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line">    cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>或者使用搜索策略，简单来说就是当选择1的时候，在剩下的里面继续选。实现如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> n,k,sum,ans;</span><br><span class="line"><span class="type">int</span> a[<span class="number">40</span>];</span><br><span class="line"><span class="type">bool</span> xuan[<span class="number">40</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> cnt,<span class="type">int</span> s)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(s == sum &amp;&amp; cnt == k)</span><br><span class="line">&#123;</span><br><span class="line">ans++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(!xuan[i])</span><br><span class="line">&#123;</span><br><span class="line">xuan[i] = <span class="number">1</span>;</span><br><span class="line"><span class="built_in">dfs</span>(s+a[i],cnt<span class="number">+1</span>);</span><br><span class="line">xuan[i] = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="comment">//输入数据</span></span><br><span class="line">cion&gt;&gt;n&gt;&gt;k&gt;&gt;sum;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line">ans = <span class="number">0</span>;</span><br><span class="line"><span class="built_in">dfs</span>(<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line">cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="深度优先搜索的剪枝策略">深度优先搜索的剪枝策略</h4><blockquote><p>此方法是DFS的改进优化，有时是DFS能否满足题目要求时间限制的关键。</p></blockquote><p>剪枝，顾名思义，就是通过一些判断，砍掉搜索树上不必要的子树。有时候，我们会发现某个结点对应的子树的状态都不是我们要的结果，那么我们其实没必要对这个分支进行搜索，砍掉这个子树，就是剪枝。</p><p>比如，如果所有的数都是正数，如果一旦发现当前的和值都已经大于sum了，那么之后不管怎么选和值都不可能回到sum了，我们也可以直接终止这个分支的搜索。我们在搜索过程中，一旦发现如果某些状态无论如何都不能找到最终的解，就可以将其“剪枝”了。说白了就是<strong>及时止损</strong>，</p><p>还是之前的那道题，假设从0-29中选择8个数使得和为200，用之前的代码会发现，如果选择的数超过了8，无论怎么选都是无效的答案，那么何不将其剪掉以提高运行效率，修改如下</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> n,k,sum,ans;</span><br><span class="line"><span class="type">int</span> a[<span class="number">40</span>];</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> i,<span class="type">int</span> cnt,<span class="type">int</span> s)</span> <span class="comment">//cnt为数的个数</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(cnt &gt; k) <span class="comment">//如果已选择的数的个数大于了题目要求的个数</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span>;<span class="comment">//直接终止这一条分支的搜索</span></span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">if</span>(i == n) <span class="comment">//i是层数</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(cnt == k &amp;&amp; s == sum)  <span class="comment">//s是数的和</span></span><br><span class="line">&#123;</span><br><span class="line">ans++;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">dfs</span>(i<span class="number">+1</span>,cnt,s);</span><br><span class="line"><span class="built_in">dfs</span>(i<span class="number">+1</span>,cnt<span class="number">+1</span>,s+a[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//输入数据</span></span><br><span class="line">cion&gt;&gt;n&gt;&gt;k&gt;&gt;sum;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;a[i];</span><br><span class="line">&#125;</span><br><span class="line">ans = <span class="number">0</span>;</span><br><span class="line"><span class="built_in">dfs</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>);</span><br><span class="line">    cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="最优性剪枝">最优性剪枝</h5><p>对于求最优解的一类问题，通常可以用最优性剪枝，比如在求解迷宫最短路的时候，如果发现当前的步数已经超过了当前最优解，那从当前状态开始的搜索都是多余的，因为这样搜索下去永远都搜不到更优的解。通过这样的剪枝，可以省去大量冗余的计算。此外，在搜索是否有可行解的过程中，一旦找到了一组可行解，后面所有的搜索都不必再进行了，这算是最优性剪枝的一个特例。</p><p>有一个n×m大小的迷宫。其中字符<code>S</code>表示起点，字符<code>T</code>表示终点，字符<code>*</code>表示墙壁，字符<code>.</code>表示平地。你需要从<code>S</code>出发走到<code>T</code>,每次只能向上下左右相邻的位置移动，并且不能走出地图，也不能走进墙壁。保证迷宫至少存在一种可行的路径，输出<code>S</code>走到<code>T</code>的最少步数。通常我们会用BFS解决这个问题，搜到的第一个结果就是答案。现在我们考虑用DFS来解决这个问题，第一个搜到的答案ans并不一定是正解，但是正解一定小于等于ans。于是如果当前步数大于等于ans就直接剪枝，并且每找到一个可行的答案，都会更新ans</p><p>实现过程</p><p>首先定义一些全局变量，n、m为迷宫的行数和列数，maze记录迷宫的地形，vis记录DFS过程中当前位置是否被访问过，dir表示每次枚举的四个方向，as记录当前到达终点的最小的步数，初始值为一个较大的数。</p><p>实现一个in函数,判断坐标是否在迷宫中。</p><p>我们来实现dfs函数，它有三个参数，x、y为当前位置的坐标，step为当前的步数。分别在函数入口处和出口处更新当前位置是否访问，然后枚举四个方向，如果(tx，ty)满足在边界内、不是墙、没被访问过，就继续扩展，并且步数增加1。</p><p>如果当前步数大于等于as就剪枝，因为继续深搜下去不可能更优了。如果当前位置为终点，就更新ans并返回。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstdio&gt;</span> </span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="type">int</span> n,m;</span><br><span class="line">string maze[<span class="number">110</span>];<span class="comment">//迷宫的地形 </span></span><br><span class="line"><span class="type">bool</span> vis[<span class="number">110</span>][<span class="number">110</span>];<span class="comment">//用矩阵记录当前位置是否被访问 </span></span><br><span class="line"><span class="type">int</span> dir[<span class="number">4</span>][<span class="number">2</span>] = &#123;&#123;<span class="number">-1</span>,<span class="number">0</span>&#125;,&#123;<span class="number">0</span>,<span class="number">-1</span>&#125;,&#123;<span class="number">1</span>,<span class="number">0</span>&#125;,&#123;<span class="number">0</span>,<span class="number">1</span>&#125;&#125;;<span class="comment">//每次枚举的四个方向 </span></span><br><span class="line"><span class="type">int</span> ans = <span class="number">100000</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//判断每次扩展的位置是不是在迷宫中</span></span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">in</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>&lt;=x &amp;&amp; x&lt;n &amp;&amp; <span class="number">0</span>&lt;=y &amp;&amp; y&lt;m;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//访问函数</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">dfs</span><span class="params">(<span class="type">int</span> x,<span class="type">int</span> y,<span class="type">int</span> step)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//剪枝情况</span></span><br><span class="line"><span class="keyword">if</span>(step &gt;=ans) </span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(maze[x][y] == <span class="string">&#x27;T&#x27;</span>)</span><br><span class="line">&#123;</span><br><span class="line">ans = step;</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">vis[x][y] = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">4</span>;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="type">int</span> tx = x + dir[i][<span class="number">0</span>];</span><br><span class="line"><span class="type">int</span> ty = y + dir[i][<span class="number">1</span>];</span><br><span class="line"><span class="keyword">if</span>(<span class="built_in">in</span>(tx.ty) &amp;&amp; maze[tx][ty] !=<span class="string">&#x27;*&#x27;</span> &amp;&amp; !vis[tx][ty])</span><br><span class="line">&#123;</span><br><span class="line"><span class="built_in">dfs</span>(tx,ty,step<span class="number">+1</span>);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">vis[x][y] = <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//测试函数</span></span><br><span class="line">cin&gt;&gt;n&gt;&gt;m;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++) </span><br><span class="line">&#123;</span><br><span class="line">cin&gt;&gt;maze[i];</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">int</span> x,y;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">0</span>;j&lt;m;j++)</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span>(maze[i][j] == <span class="string">&#x27;S&#x27;</span>)</span><br><span class="line">&#123;</span><br><span class="line">x = i,y=j;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">dfs</span>(x,y,<span class="number">0</span>);</span><br><span class="line">cout&lt;&lt;ans&lt;&lt;endl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="重复性剪枝">重复性剪枝</h5><p>对于某一些特定的搜索方式，一个方案可能会被搜索很多次，这样是没必要的。<br>再来看这个问题：给定n个整数，要求选出K个数，使得选出来的K个数的和为sum.<br>如果搜索方法是每次从剩下的数里选一个数，一共搜到第k层，那么1,2,3这个选取方法能被搜索到6次，这是没必要的，因为我们只关注选出来的数的和，而根本不会关注选出来的数的顺序，所以这里可以用重复性剪枝。</p><p>我们规定选出来的数的位置是递增的，在搜索的时候，用一个参数来记录上一次选取的数的位置，那么此次选择我们从这个数之后开始选取，这样最后选出来的方案就不会重复了。</p><p><strong>奇偶性剪枝</strong></p><h3 id="广度优先搜索-BFS">广度优先搜索(BFS)</h3><p>队列(queue)是一种线性的数据结构，和栈一样是一种运算受限制的线性表。其限制只允许从表的前端(front)进行删除操作，而在表的后端(rar)进行插入操作。一般允许进行插入的一端我们称为队尾，允许删除的一端称为队首。队列的插入操作又叫入队，队列的删除操作又叫出队。<br>C++也有实现的STL，示例如下. <strong>注意队列中是没有清空的</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;queue&gt;</span></span></span><br><span class="line"><span class="comment">//注意这里没有写using namespace std; 如果你写了 后面调用对应函数可以省略写std::</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// 创建一个整数队列</span></span><br><span class="line">    std::queue&lt;<span class="type">int</span>&gt; q;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 向队列中添加元素</span></span><br><span class="line">    q.<span class="built_in">push</span>(<span class="number">10</span>);</span><br><span class="line">    q.<span class="built_in">push</span>(<span class="number">20</span>);</span><br><span class="line">    q.<span class="built_in">push</span>(<span class="number">30</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 打印队列中的元素数量</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;队列中的元素数量: &quot;</span> &lt;&lt; q.<span class="built_in">size</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 打印队首元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;队首元素: &quot;</span> &lt;&lt; q.<span class="built_in">front</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 打印队尾元素</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;队尾元素: &quot;</span> &lt;&lt; q.<span class="built_in">back</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 移除队首元素</span></span><br><span class="line">    q.<span class="built_in">pop</span>();</span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;移除队首元素后，队首元素: &quot;</span> &lt;&lt; q.<span class="built_in">front</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 再次打印队列中的元素数量</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;队列中的元素数量: &quot;</span> &lt;&lt; q.<span class="built_in">size</span>() &lt;&lt; std::endl;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//判断队列是否为空</span></span><br><span class="line">    std::cout &lt;&lt; <span class="string">&quot;队列是否为空: &quot;</span>&lt;&lt; q.<span class="built_in">empty</span>() &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>广度优先搜索，又称宽度优先搜索，简称bfs,我们以后都会用bfs来表示广度优先搜索。与深度优先搜索不同的是，广度优先搜索会先将与起始点距离较近的点搜索完毕，再继续搜索较远的点，而深搜却是沿着一个分支搜到最后。<br>bfs从起点开始，优先搜索离起点最近的点，然后由这个最近的点扩展其他稍近的点，这样一层一层的扩展，就像水波扩散一样。</p><p>这里BFS需要借助队列实现，实现步骤抽象如下</p><ol><li>初始的时候把起始点放到队列中，并标记起点访问。</li><li>如果队列不为空，从队列中取出一个元素x,否则算法结束。</li><li>访问和x相连的所有点v，如果U没有被访问，把v入队，并标记已经访问。</li><li>重复执行步骤2。</li></ol><p>代码框架如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">void bfs(起始点)</span><br><span class="line">&#123;</span><br><span class="line">将起始点放入队列;</span><br><span class="line">标记起点访问;</span><br><span class="line">while(如果队列不为空)</span><br><span class="line">&#123;</span><br><span class="line">访问队列中队首元素X;</span><br><span class="line">删除队首元素;</span><br><span class="line">for(x 所有相邻点)</span><br><span class="line">&#123;</span><br><span class="line">if(该点未被访问过且合法)</span><br><span class="line">&#123;</span><br><span class="line">将该点加入队列末尾;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="动态规划">动态规划</h3><p>其实就是后面问题的解答可以由前面问题的解递推而来，这种解法也被称为递推算法。</p><p>递推也是经常被使用的一种简单算法。递推是一种用若干步可重复的简单运算来描述复杂问题的方法。递推的特点在于，每一项都和他前面的若干项有一定关联，这种关联一般可以通过递推关系式来表示，可以通过其前面若干项得出某项的数据。对于递推问题的求解一般从初始的一个或若干个数据项出发，通过递推关系式逐步推进，从而得出想要的结果，这种求解问题的方法叫递推法。其中，初始的若干数据项称为边界。</p><p><strong>以一个例子引入动态规划的问题</strong><br>设n封信，所有信都装错的情况为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">F_{n}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>.当添加第几封信的时候，我们可以直接想到，这封信与前n-1封信中的一封放错，那么我们就有n-1种选择。所以我们就可以得到<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>×</mo><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F_{n-1}×(n-1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span>种情况。<br>这个时候仿佛已经是最后的答案了，但是我们如果仔细想的话，我们会发现我们疏漏了一种情况。因为前n-1封信都是错排。所以<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msub></mrow><annotation encoding="application/x-tex">F_{n-1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span>的方案里面不会存在有一封信放在正确的位置。但是如果有一封信放在正确的位置，那么第几封信与他错排，依然是一种方案。这个时候就相当于n-2封信相互错排，前n-1封中的一封信和第几封信错排。所以我们就可以得到<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mrow><mi>n</mi><mo>−</mo><mn>2</mn></mrow></msub><mo>×</mo><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F_{n-2}×(n-1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span>的方案数。<br>到这里，我们已经可以得出这个递推式了，根据乘法原理：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mi>n</mi></msub><mo>=</mo><mo stretchy="false">(</mo><mi>n</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo stretchy="false">(</mo><msub><mi>F</mi><mrow><mi>n</mi><mo>−</mo><mn>1</mn></mrow></msub><mo>+</mo><msub><mi>F</mi><mrow><mi>n</mi><mo>−</mo><mn>2</mn></mrow></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F_{n}=(n-1)(F_{n-1}+F_{n-2})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 我们再想一下，代码中的初始条件，也就是边界值。在只有一封信的时候，不可能装错，那么<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mn>1</mn></msub><mo>=</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">F_{1}=0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>；有两封信的时候，装错的方案数为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>F</mi><mn>2</mn></msub><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">F_{2}=1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>。这就是著名的错排公式。</p><p>错排方式实现</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="keyword">typedef</span> <span class="type">long</span> <span class="type">long</span> ll;</span><br><span class="line"><span class="type">const</span> <span class="type">int</span> N = <span class="number">1e3</span><span class="number">+9</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> f[N];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> n;</span><br><span class="line">cin&gt;&gt;n;</span><br><span class="line">f[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line">f[<span class="number">2</span>] = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">3</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">f[i] = (f[i<span class="number">-1</span>]+f[i<span class="number">-2</span>]*(i<span class="number">-1</span>));</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;f[n]&lt;&lt;endl;</span><br><span class="line">ll a = <span class="number">0</span>,b = <span class="number">1</span>,c=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">3</span>;i&lt;=n;i++)</span><br><span class="line">&#123;</span><br><span class="line">c = (a+b)*(i<span class="number">-1</span>);</span><br><span class="line">a = b;</span><br><span class="line">b = c;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(n!=<span class="number">1</span>)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;c&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;<span class="number">0</span>&lt;&lt;endl;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>二维递推</strong></p><p>例题1：杨辉三角——请求出杨辉三角的第n行，第m项的数字是什么？通过递推式表达出来</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 用数据表示为</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">1</span></span><br><span class="line"><span class="comment">1 1</span></span><br><span class="line"><span class="comment">1 2 1</span></span><br><span class="line"><span class="comment">1 3 3 1</span></span><br><span class="line"><span class="comment">……</span></span><br><span class="line"><span class="comment">整理出递推式子为:f[i][j] = f[i-1][j-1]+f[i-1][j]</span></span><br><span class="line"><span class="comment">*/</span></span><br></pre></td></tr></table></figure><p>动态规划是编程解题的一种重要手段。1951年美国数学家R.Bellman等人，根据一类多阶段问题的特点，把多阶段决策问题变换为一系列互相联系的单阶段问题，然后逐个加以解决。与此同时，他提出了解决这类问题的“最优化原理”，从而创建了解决最优化问题的一种新方法：动态规划。动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中，可能会有许多可行解。每一个解都对应于一个值，我们希望找到具有最优值的解。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到，只要它被计算过，就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样，但它们具有相同的填表格式。</p><h3 id="查找">查找</h3><p>库函数只能对数组进行二分查找。对一个数组进行二分查找的前提是这个<strong>数组中的元素是单调的</strong>，一般为单调不减或者单调不增（需要修改比较函数），例如[1,5,5,9,11] 是单调不减</p><p>binary_search是C++标准库中的一个算法函数，用于在已排序的序列（例如数组array或容器vector）<br>中查找特定元素。它通过<strong>二分查找算法</strong>来确定序列中是否存在目标元素。函数返回一个bool值，表示目标元素是否存在于序列中。如果需要获取找到的元素的位置，可以使用<code>std:lower bound</code>函数或<code>std:upper_bound</code>函数。</p><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在BiSearch.h文件中</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span>  <span class="comment">//要使用二分法的函数、lower_bound和upper_bound需要导入算法库</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_BiSearch</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; numbers = &#123;<span class="number">1</span>,<span class="number">3</span>,<span class="number">5</span>,<span class="number">7</span>,<span class="number">9</span>&#125;;</span><br><span class="line"><span class="type">int</span> target = <span class="number">5</span>;</span><br><span class="line"><span class="type">bool</span> flag = <span class="built_in">binary_search</span>(numbers.<span class="built_in">begin</span>(),numbers.<span class="built_in">end</span>(),target);</span><br><span class="line"><span class="keyword">if</span>(flag)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;<span class="string">&quot;目标元素&quot;</span>&lt;&lt;target&lt;&lt;<span class="string">&quot;被找到&quot;</span>&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//在main.cpp文件中</span></span><br><span class="line"><span class="comment">//这里主要负责测试头文件定义的测试函数 </span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//测试二分法</span></span><br><span class="line"><span class="built_in">Test_BiSearch</span>() ;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><code>lower_bound</code>与<code>upper_bound</code>前提：<strong>数组必须为非降序</strong>。如果要在非升序的数组中使用，可以通过修改比较函数实现(方法与sort自定义比较函数类似)<br><code>lower_bound(st,ed,x)</code>返回地址[st,ed)中第一个大于等于x的元素的<strong>地址</strong>。地址-首地址=下标<br><code>upper_bound(st,ed,x)</code>返回地址[st,ed)中第一个大于x的元素的<strong>地址</strong>。如果不存在则返回最后一个元素的下一个位置，在vector中即end()。</p><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在BiSearch.h文件中</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_bound</span><span class="params">(<span class="type">void</span>)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化 </span></span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v = &#123;<span class="number">5</span>,<span class="number">1</span>,<span class="number">7</span>,<span class="number">3</span>,<span class="number">10</span>,<span class="number">18</span>,<span class="number">9</span>&#125;;</span><br><span class="line"><span class="built_in">sort</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>());</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;v.<span class="built_in">size</span>();i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;i&lt;&lt;<span class="string">&#x27; &#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//找到数组中第一个大于等于8元素的下标</span></span><br><span class="line">cout&lt;&lt;(<span class="built_in">lower_bound</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>(),<span class="number">8</span>)-v.<span class="built_in">begin</span>())&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//在main.cpp文件中</span></span><br><span class="line"><span class="comment">//这里主要负责测试头文件定义的测试函数 </span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//测试bound</span></span><br><span class="line"><span class="built_in">Test_bound</span>(); </span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例题：<a href="https://www.lanqiao.cn/problems/1389/learning/?page=1&amp;first_category_id=1&amp;second_category_id=6&amp;problem_id=1389">1.二分查找数组元素 - 蓝桥云课</a></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;vector&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">// 请在此输入您的代码</span></span><br><span class="line">  <span class="comment">//初始化</span></span><br><span class="line">  <span class="type">int</span> data[<span class="number">200</span>];</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">200</span>;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    data[i] = <span class="number">4</span>*i<span class="number">+6</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="type">int</span> target = <span class="number">0</span>;</span><br><span class="line">  <span class="built_in">scanf</span>(<span class="string">&quot;%d&quot;</span>,&amp;target);</span><br><span class="line">  cout&lt;&lt;(<span class="built_in">lower_bound</span>(data,data<span class="number">+200</span>,target)-data);<span class="comment">//对于数组之类的 begin指的是首地址。其他同理</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="其他常见的库函数">其他常见的库函数</h3><h4 id="memset">memset</h4><p>memset()是一个用于设置内存块值的函数。它的原型定义在<code>&lt;cstring&gt;</code>头文件中，函数的声明如下：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> * <span class="title">memset</span><span class="params">(<span class="type">void</span>* ptr,<span class="type">int</span> value,<span class="type">size_t</span> num)</span></span>;</span><br></pre></td></tr></table></figure><p>其中：ptr:指向要设置值的内存块的指针。value:要设置的值，通常是一个整数(8位二进制数)。num:要设置的字节数。</p><p>函数将ptr指向的内存块的前num个字节设置为value的值。它返回一个指向ptr的指针。通常用于初始化内存块，将其设置为特定的值</p><p>示例：将一个整型数组所有元素设置为0</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> arr[<span class="number">10</span>];</span><br><span class="line"><span class="built_in">memset</span>(arr,<span class="number">0</span>,<span class="built_in">sizeof</span>(arr));</span><br></pre></td></tr></table></figure><p>需要注意的是，memset()函数对于非字符类型(即不是char类型的)的数组可能会产生未定义行为。需要使用遍历将其设置对应的值.<strong>memset会将每个byte设置为value</strong>,比图 比如说你设置的value为1,类型为int,那么二进制为00000001 00000001 00000001 00000001</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> a[<span class="number">5</span>] ;</span><br><span class="line"><span class="built_in">memset</span>(a,<span class="number">1</span>,<span class="built_in">sizeof</span>(a));<span class="comment">//在可能的情况下最好使用二进制、八进制，十六进制作为value</span></span><br><span class="line"><span class="comment">//示例 memset(a,0x33,sizeof(a))  16进制的33</span></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">5</span>;i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;<span class="built_in">bitset</span>&lt;<span class="number">32</span>&gt;(a[i])&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;<span class="comment">//输出结果为00000001</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="swap">swap</h4><p>swap(T&amp;a,T&amp;b)函数接受两个参数：<br>1.a:要交换值的第一个变量的引用<br>2.b:要交换值的第二个变量的引用，<br>swap()函数通过将第一个变量的值存储到临时变量中，然后将第二个变量的值赋给第一个变量，最后将临时变量的值赋给第二<br>个变量，实现两个变量值的交换。swap()函数可以用于<strong>交换任意类型的变量</strong>，包括基本类型(如整数、浮点数等）和自定义类型<br>(如结构体、类对象等)以下是一个示例，展示如何使用swap()函数交换两个整数的值：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">10</span>;</span><br><span class="line"><span class="type">int</span> b = <span class="number">20</span>;</span><br><span class="line">std::<span class="built_in">swap</span>(a,b);</span><br></pre></td></tr></table></figure><h4 id="reverse">reverse</h4><p>反转容器中元素顺序的函数,它的原型定义在<code>&lt;algorithm&gt;</code>头文件中</p><p>reverse()函数接受两个参数：<br>1.first:指向容器中要反转的<strong>第一个元素</strong>的迭代器。<br>2.last:指向容器中要反转的<strong>最后一个元素的下一个位置</strong>的迭代器。<br>reverse()函数将[first,last)范围内的元素顺序进行反转。也就是说，它会将frst,last)范围内的元素按相反的顺序重新排列。<br>reverse()函数可用于反转各种类型的容器，包括数组、向量、链表等。以下是一个示例，展示如何使用reverse(O函数反转一个整型向量的元素顺序：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在OtherFun.h文件里面</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_Reverse</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v = &#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>&#125;;</span><br><span class="line"><span class="built_in">reverse</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>());</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;v.<span class="built_in">size</span>();i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;v[i]&lt;&lt;<span class="string">&#x27; &#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//在main.cpp文件里面</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="built_in">Test_Reverse</span>(); </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>需要注意的是，reverse函数只能用于支持双向迭代器的容器，因为它需要能够向前和向后遍历容器中的元素。对于只支持单向迭代器的容器（如前向链表），无法使用reverse函数进行反转。</p><h4 id="unique">unique</h4><p>去除容器中相邻重复元素的函数，需要导入头文件<code>&lt;algorithm&gt;</code></p><p>在上述示例中，std:unique(vec.begin(),vec.end())将整型向量vec中的相邻重复元素去除。最终输出的结果是1 2 3 4 5.需要注意的是，unique()函数<strong>只能去除相邻的重复元素</strong>，如果容器中存在非相邻的重复元素，则无法去除。如果需要去除所有重复元素，而不仅仅是相邻的重复元素，<strong>可以先对容器进行排序，然后再使用unique()函数</strong>。</p><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在OtherFun.h文件里面</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_Unique</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="type">int</span> a[] = &#123;<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">2</span>,<span class="number">3</span>&#125;;</span><br><span class="line"><span class="type">int</span> n = <span class="built_in">unique</span>(a,a<span class="number">+5</span>)-a;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;n;i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;a[i]&lt;&lt;<span class="string">&#x27; &#x27;</span> ;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//在main.cpp文件里面</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="built_in">Test_Unique</span>(); <span class="comment">//结果为1 2 3</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="全排列">全排列</h4><p>next_permutation函数用于生成当前序列的下一个排列。它按照字典序对序列进行重新排列，如果存在下一个排列，则将当前序列更改为下一个排列，并返回tue;如果当前序列已经是最后一个排列，则将序列更改为第一个排列，并返回false。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//在OtherFun.h文件里面</span></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_permutation</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v = &#123;<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//生成下一个排列</span></span><br><span class="line"><span class="keyword">while</span>(<span class="built_in">next_permutation</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>()))</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;<span class="string">&quot;下一个排序&quot;</span>;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">3</span>;i++) </span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;v[i]&lt;&lt;<span class="string">&#x27; &#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line">cout&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125; </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//在main.cpp文件里面</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//测试全排列函数 </span></span><br><span class="line"><span class="built_in">Test_permutation</span>();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>prev_permutation函数与next_permutation函数相反，它用于生成当前序列的上一个排列</p><h4 id="最值函数">最值函数</h4><p>min(a，b)返回a和b中较小的那个值，只能传入两个值，或传入一个列表(比如min({1,2,3,4})。max同理<br>min_element(St,ed)返回地址[st,ed)中最小的那个值的<strong>地址</strong>（迭代器），传入参数为两个地址或迭代器。<br>max_element(st,ed)返回地址[st,ed)中最大的那个值的地址（迭代器），传入参数为两个地址或迭代器。时间复杂度均为O(n),n为数组大小（由传入的参数决定）</p><p>但是要注意的是，返回值类型是<code>size_t</code> 一般用long long接收</p><p>示例</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_TheValue</span><span class="params">(<span class="type">void</span>)</span> </span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化</span></span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v = &#123;<span class="number">5</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">11</span>&#125; ;</span><br><span class="line"></span><br><span class="line"><span class="comment">//输出最大的元素 通过*解引用得到值</span></span><br><span class="line">cout&lt;&lt;*<span class="built_in">max_element</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">end</span>()) &lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//在main.cpp文件里面</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//测试最值函数</span></span><br><span class="line"><span class="built_in">Test_TheValue</span>(); <span class="comment">//输出结果为11</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>nth_element函数</strong></p><p>nth_element(st,k,ed)进行部分排序，返回值为void() 传入参数为三个地址或迭代器。其中第二个参数位置的元素将处于正确位置，<strong>其他位置元素的顺序可能是任意的，但前面的都比它小，后面的都比它大</strong>。时间复杂度O(n)。</p><p><strong>举例：求第三小的数字</strong>，对于 a[9]={4,7,6,9,1,8,2,3,5};nth_element(a,a+2,a+9)，将下标为2，也就是第3个数放在正确的位置，求的是第3小的数a[2]。（下标从零开始）</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">Test_nth</span><span class="params">(<span class="type">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//初始化</span></span><br><span class="line">vector&lt;<span class="type">int</span>&gt; v = &#123;<span class="number">5</span>,<span class="number">1</span>,<span class="number">7</span>,<span class="number">3</span>,<span class="number">10</span>,<span class="number">18</span>,<span class="number">9</span>&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">//输出最大的元素</span></span><br><span class="line"><span class="built_in">nth_element</span>(v.<span class="built_in">begin</span>(),v.<span class="built_in">begin</span>()<span class="number">+3</span>,v.<span class="built_in">end</span>()) ;<span class="comment">//这里找的是第四小的数</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;<span class="number">7</span>;i++)</span><br><span class="line">&#123;</span><br><span class="line">cout&lt;&lt;v[i]&lt;&lt;<span class="string">&#x27; &#x27;</span>;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//在main.cpp文件里面</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="comment">//测试最值函数</span></span><br><span class="line"><span class="built_in">Test_nth</span>();<span class="comment">//输出结果为3 1 5 7 9 18 10</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例题</p><p><a href="https://www.lanqiao.cn/problems/497/learning/?page=1&amp;first_category_id=1&amp;problem_id=497">1.成绩分析 - 蓝桥云课-497</a></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;algorithm&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;bits/stdc++.h&gt;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">  <span class="comment">//人数</span></span><br><span class="line">  <span class="type">int</span> num  =<span class="number">0</span>;</span><br><span class="line">  cin&gt;&gt;num;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//成绩初始化</span></span><br><span class="line">  <span class="type">int</span> arr[num];</span><br><span class="line">  <span class="type">int</span> sum = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">for</span>(<span class="type">int</span> i = <span class="number">0</span>;i&lt;num;i++)</span><br><span class="line">  &#123;</span><br><span class="line">    cin&gt;&gt;arr[i];</span><br><span class="line">    sum+=arr[i];</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  cout&lt;&lt;*<span class="built_in">max_element</span>(arr,arr+num)&lt;&lt;<span class="string">&#x27;\n&#x27;</span>&lt;&lt;*<span class="built_in">min_element</span>(arr,arr+num)&lt;&lt;<span class="string">&#x27;\n&#x27;</span>;</span><br><span class="line">  cout&lt;&lt;fixed&lt;&lt;<span class="built_in">setprecision</span>(<span class="number">2</span>)&lt;&lt;<span class="number">1.0</span>*sum/num;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="刷题系列">刷题系列</h2><p>读者可以参考以下的系列博客有针对的刷题</p><ol class="series-items"><li><a href="/posts/lanqiaocup-series-one/" title="算法系列(一)蓝桥杯及其知识体系">算法系列(一)蓝桥杯及其知识体系</a></li><li><a href="/posts/lanqiaocup-series-three/" title="算法系列(三)蓝桥杯_算法高阶(一)">算法系列(三)蓝桥杯_算法高阶(一)</a></li><li><a href="/posts/lanqiaocup-series-five/" title="算法系列(三)蓝桥杯_算法高阶(三)">算法系列(三)蓝桥杯_算法高阶(三)</a></li><li><a href="/posts/lanqiaocup-series-four/" title="算法系列(三)蓝桥杯_算法高阶(二)">算法系列(三)蓝桥杯_算法高阶(二)</a></li><li><a href="/posts/lanqiaocup-series-two/" title="算法系列(二)蓝桥杯_算法基础">算法系列(二)蓝桥杯_算法基础</a></li><li><a href="/posts/algorithm-restart/" title="算法系列(四)从零开始的算法刷题生活">算法系列(四)从零开始的算法刷题生活</a></li></ol><h2 id="参考">参考</h2><ol><li><a href="https://www.bilibili.com/video/BV1Lb4y1k7K3/?share_source=copy_web&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">蓝桥杯比赛视频教程（入门学习+算法辅导)</a> 建议看前41节 重点是他讲的知识点，由于他讲题特别快不建议按照他的课刷题，建议自行在蓝桥杯题库中刷题。</li><li><a href="https://leetcode.cn/circle/discuss/E3yavq/">力扣刷题攻略</a>  读者可以在这里参考刷题。</li><li>蓝桥云课C++班，作者谢子杨</li></ol>]]></content>
    
    
    <summary type="html">总结了C/C++赛道蓝桥杯的知识点以及背后的算法原理，旨在为竞赛和后续算法学习打下基础</summary>
    
    
    
    <category term="algorithm" scheme="https://lloydkai.cn/categories/algorithm/"/>
    
    
    <category term="C" scheme="https://lloydkai.cn/tags/C/"/>
    
    <category term="C++" scheme="https://lloydkai.cn/tags/C/"/>
    
  </entry>
  
  <entry>
    <title>MySQL学习笔记(二)进阶篇</title>
    <link href="https://lloydkai.cn/posts/mysql-series-two/"/>
    <id>https://lloydkai.cn/posts/mysql-series-two/</id>
    <published>2024-11-22T02:32:29.000Z</published>
    <updated>2026-04-23T01:48:08.577Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/06/10/q24e9CMDLd8cYfa.png" alt></p><blockquote><p>注：本篇博客大部分是黑马pdf中的内容，根据我自己学习的实际情况进行修改和补充。</p></blockquote><h1>准备工作</h1><ol><li>准备好虚拟机并安装好mysql</li></ol><h1>存储引擎</h1><p>概念：<strong>存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式</strong> 。存储引擎是基于表的，而不是基于库的，所以存储引擎也可被称为表类型。我们可以在创建表的时候，来指定选择的存储引擎，如果没有指定将自动选择默认的存储引擎。</p><h2 id="MySQL体系结构">MySQL体系结构</h2><p>参考博客<a href="https://blog.csdn.net/qq_45938466/article/details/107941557">数据库工作原理</a></p><p><img src="https://s2.loli.net/2024/11/26/9XL8m1xhEAgzGFU.png" alt="100_演示图_01.png"></p><ol><li>连接层<br><strong>最上层</strong>是一些客户端和链接服务，包含本地sock通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了<strong>线程池</strong>的概念，为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全链接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。</li><li>服务层<br>第二层架构主要完成大多数的核心服务功能，如SQL接口，并完成缓存的查询，SQL的分析和优化，部分内置函数的执行。所有跨存储引擎的功能也在这一层实现，如 过程、函数等。在该层，服务器会解析查询并创建相应的内部解析树，并对其完成相应的优化如确定表的查询的顺序，是否利用索引等，最后生成相应的执行操作。如果是select语句，服务器还会查询内部的缓存，如果缓存空间足够大，这样在解决大量读操作的环境中能够很好的提升系统的性能。</li><li>引擎层<br>存储引擎层， 存储引擎真正的<strong>负责了MySQL中数据的存储和提取</strong>，服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能，这样我们可以根据自己的需要，来选取合适的存储引擎。数据库中的索引是在存储引擎层实现的。</li><li>存储层<br>数据存储层， 主要是将数据(如: redolog、undolog、数据、索引、二进制日志、错误日志、查询日志、慢查询日志等)存储在文件系统之上，并完成与存储引擎的交互。和其他数据库相比，MySQL有点与众不同，它的架构可以在多种不同场景中应用并发挥良好作用。主要体现在存储引擎上，插件式的存储引擎架构，将查询处理和其他的系统任务以及数据的存储提取分离。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。</li></ol><h2 id="语法">语法</h2><ol><li>创建表时指定存储引擎</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE TABLE</span> 表名(</span><br><span class="line">字段<span class="number">1</span> 字段<span class="number">1</span>类型 [ COMMENT 字段<span class="number">1</span>注释 ] ,</span><br><span class="line">......</span><br><span class="line">字段n 字段n类型 [COMMENT 字段n注释 ]</span><br><span class="line">) ENGINE <span class="operator">=</span> 存储引擎 [ COMMENT 表注释 ] ;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- MySQL中默认的储存引擎为InnoDB</span></span><br><span class="line"><span class="comment">-- 示例 使用默认的存储引擎创建表</span></span><br><span class="line"><span class="keyword">show</span> <span class="keyword">create table</span> account;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/8Vtqa1grxSKcBsT.png" alt="001_存储引擎_01.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建表my_myisam,并指定MyISAM储存引擎</span></span><br><span class="line"><span class="keyword">create table</span> my_myisam(</span><br><span class="line">                          id <span class="type">int</span>,</span><br><span class="line">                          name <span class="type">varchar</span>(<span class="number">10</span>)</span><br><span class="line">) engine <span class="operator">=</span> MyISAM;</span><br><span class="line"><span class="comment">-- 以ibd为后缀的都是使用InnoDB引擎的表</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/EZjosleKiPkRVxM.png" alt="001_存储引擎_03.png"></p><ol start="2"><li>查询当前数据库支持的存储引擎</li></ol><p>语法：<code>show engines;</code></p><p><img src="https://s2.loli.net/2024/11/26/1NiTYUDPLfIlKeG.png" alt="001_存储引擎_02.png"></p><p>可以看到&quot;engine&quot;这一行中InnoDB的&quot;Support&quot;字段为&quot;<strong>DEFAULT</strong>&quot;,也就是<strong>默认</strong>的意思。</p><h2 id="存储引擎的区别和特点">存储引擎的区别和特点</h2><p>重点讲解InnoDB，MyISAM和Memory存储引擎的特点</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">InnoDB</button><button type="button" class="tab">MyISAM</button><button type="button" class="tab">Memory</button></div><div class="tab-contents"><div class="tab-item-content active"><ol><li>介绍<br>InnoDB是一种兼顾高可靠性和高性能的通用存储引擎，在 MySQL 5.5 之后，InnoDB是默认的MySQL 存储引擎。</li><li>特点<br>DML操作遵循ACID模型，支持<strong>事务</strong>；<strong>行级锁</strong>，提高并发访问性能；支持<strong>外键</strong>FOREIGN KEY<strong>约束</strong>，保证数据的完整性和正确性；</li><li>文件<br>xxx.ibd：xxx代表的是表名，innoDB引擎的每张表都会对应这样一个表空间文件，存储该表的表结构（frm-早期的 、sdi-新版的）、数据和索引。参数：innodb_file_per_table</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> variables <span class="keyword">like</span> <span class="string">&#x27;innodb_file_per_table&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/hj7oSZl5rtq3KIR.png" alt="001_存储引擎_04.png"></p><p>如果该参数开启，代表对于InnoDB引擎的表，每一张表都对应一个ibd文件。 我们直接打开MySQL的数据存放目录：C:\ProgramData\MySQL\MySQL Server 8.0\Data(<strong>按照你MySQL的安装路径修改</strong>)， 这个目录下有很多文件夹，不同的文件夹代表不同的数据库.任意打开一个自建的文件夹，就会发现里面有许多后缀为.ibd的文件，每一个ibd文件就对应一张表，比如：我们有一张表 account，就有这样的一个account.ibd文件，而在这个ibd文件中不仅存放表结构、数据，还会存放该表对应的索引信息。 而该文件是基于二进制存储的，不能直接基于记事本打开，我们可以使用mysql提供的一个指令 ibd2sdi ，通过该指令就可以从ibd文件中提取sdi信息，而sdi数据字典信息中就包含该表的表结构。</p><p><img src="https://s2.loli.net/2024/11/26/vI6j8VMYKPaJsQ9.png" alt="001_存储引擎_05.png"></p><ol start="4"><li>逻辑存储结构</li></ol><p><img src="https://s2.loli.net/2024/11/26/G6DotI1dn4kKCv2.png" alt="001_存储引擎_06.png"></p><ul><li>表空间(Tablespace): InnoDB存储引擎逻辑结构的最高层，ibd文件其实就是表空间文件，在表空间中可以包含多个Segment段。如果用户启用了参数 innodb_file_per_table(在8.0版本中默认开启) ，则每张表都会有一个表空间（xxx.ibd），一个mysql实例可以对应多个表空间，用于存储记录、索引等数据</li><li>段(Segment): 表空间是由各个段组成的， 分为数据段（Leaf node segment）、索引段（Non-leaf node segment）、回滚段<br>（Rollback segment）  等,InnoDB中对于段的管理，都是引擎自身完成，不需要人为对其控制，InnoDB是索引组织表，数据段就是B+树的叶子节点， 索引段即为B+树的非叶子节点。段用来管理多个Extent（区）。</li><li>区(Extent): 区是表空间的单元结构，每个区的大小为1M。 默认情况下， InnoDB存储引擎页大小为16K， 即一个区中一共有64个连续的页。</li><li>页(Page): 页是组成区的最小单元，页也是InnoDB 存储引擎磁盘管理的最小单元，每个页的大小默认为 16KB。为了保证页的连续性，InnoDB 存储引擎每次从磁盘申请 4-5 个区。</li><li>行(Row): InnoDB 存储引擎是面向行的，也就是说数据是按行进行存放的，在每一行中除了定义表时所指定的字段以外，还包含两个隐藏字段.一个是Trx_id：每次对某条记录进行改动时，都会把对应的事务id赋值给trx_id隐藏列。；另一个是Roll_pointer：每次对某条引记录进行改动时，都会把旧的版本写入到undo日志中，然后这个隐藏列就相当于一个指针，可以通过它来找到该记录修改前的信息</li></ul></div><div class="tab-item-content"><ol><li>介绍<br>MyISAM是MySQL早期的默认存储引擎。</li><li>特点<br>不支持事务，不支持外键;支持表锁，不支持行锁;访问速度快</li><li>文件<br>xxx.sdi：存储表结构信息；xxx.MYD: 存储数据；xxx.MYI: 存储索引</li></ol></div><div class="tab-item-content"><ol><li>介绍<br>Memory引擎的表数据时存储在内存中的，由于受到硬件问题、或断电问题的影响，只能将这些表作为临时表或缓存使用。</li><li>特点<br>内存存放；hash索引（默认）</li><li>文件<br>xxx.sdi：存储表结构信息</li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><table><thead><tr><th>特点</th><th>InnoDB</th><th>MyISAM</th><th>Memory</th></tr></thead><tbody><tr><td>存储限制</td><td>64TB</td><td>有</td><td>有</td></tr><tr><td>事务安全</td><td>支持</td><td>-</td><td>-</td></tr><tr><td>锁机制</td><td>行锁</td><td>表锁</td><td>表锁</td></tr><tr><td>B+tree索引</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>Hash索引</td><td>-</td><td>-</td><td>支持</td></tr><tr><td>全文索引</td><td>支持(5.6版本之后)</td><td>支持</td><td>-</td></tr><tr><td>空间使用</td><td>高</td><td>低</td><td>N/A</td></tr><tr><td>内存使用</td><td>高</td><td>低</td><td>中等</td></tr><tr><td>批量插入速度</td><td>低</td><td>高</td><td>高</td></tr><tr><td>支持外键</td><td>支持</td><td>-</td><td>-</td></tr></tbody></table><blockquote><p>InnoDB引擎与MyISAM引擎的区别 ?<br>①. InnoDB引擎, 支持事务, 而MyISAM不支持。<br>②. InnoDB引擎, 支持行锁和表锁, 而MyISAM仅支持表锁, 不支持行锁。<br>③. InnoDB引擎, 支持外键, 而MyISAM是不支持的。</p><p>具体其他细节可以参考官方文档：<a href="https://dev.mysql.com/doc/refman/8.0/en/innodb-introduction.html">MySQL :: MySQL 8.0 Reference Manual :: 17.1 Introduction to InnoDB</a></p></blockquote><h2 id="存储引擎的选择">存储引擎的选择</h2><blockquote><p>很多情况下技术的选择都具有局限性和折中性，不存在完美的选择，只有相对好的选择。</p></blockquote><p>在选择存储引擎时，应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统，还可以根据实际情况选择多种存储引擎进行组合。</p><ol><li>InnoDB: 是Mysql的默认存储引擎，支持事务、外键。如果应用对事务的完整性有比较高的要求，在并发条件下要求数据的一致性，数据操作除了插入和查询之外，还包含很多的更新、删除操作，那么InnoDB存储引擎是比较合适的选择。</li><li>MyISAM ： 如果应用是以读操作和插入操作为主，只有很少的更新和删除操作，并且对事务的完整性、并发性要求不是很高，那么选择这个存储引擎是非常合适的。</li><li>MEMORY：将所有数据保存在内存中，访问速度快，通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制，太大的表无法缓存在内存中，而且无法保障数据的安全性</li></ol><h1>索引</h1><p>概念：索引（index）是帮助MySQL高效获取数据的数据结构(有序)。在数据之外，数据库系统还维护着满足特定查找算法的数据结构，这些数据结构以某种方式引用（指向）数据， 这样就可以在这些数据结构上实现高级查找算法，这种数据结构就是索引。简单来说就是数据结构在数据库中的应用(＾－＾)。</p><p>有索引和无索引搜索时间比较</p><p><img src="https://s2.loli.net/2024/11/26/UC9EAFGZgMlhL5a.png" alt="002_存储索引_01.png"></p><p>在表中数据较少的时候相差不大，但如果是千万级别的数据，差距就尤其明显。这是因为在无索引情况下，就需要从第一行开始扫描，一直扫描到最后一行，我们称之为<strong>全表扫描</strong>，其性能很低。 如果我们针对于这张表建立了索引 (比如二叉树) ,查询时就会按照二叉树的索引进行查找，二叉树搜索和穷举法哪个时间复杂度更小，不用我多说了吧（￣︶￣）。</p><p>索引的<strong>优点</strong>在于<strong>提高</strong>数据检索的<strong>效率</strong>，降低数据库的IO成本；通过索引列对数据进行排序，降低数据排序的成本，<strong>降低CPU的消耗</strong>，其<strong>缺点</strong>是索引列也是要<strong>占用空间</strong>的；索引大大提高了查询效率，同时却也<strong>降低更新表的速度</strong>， 如对表进行INSERT、UPDATE、DELETE时，效率降低。</p><h2 id="索引结构">索引结构</h2><p>不同的存储引擎支持的索引结构不同，主要包含以下几种。</p><table><thead><tr><th>索引结构</th><th>描述</th></tr></thead><tbody><tr><td>B+Tree索引</td><td>最常见的索引类型，大部分引擎都支持 B+ 树索引</td></tr><tr><td>Hash索引</td><td>底层数据结构是用哈希表实现的, 只有精确匹配索引列的查询才有效, 不 支持范围查询</td></tr><tr><td>R-tree(空间索 引）</td><td>空间索引是MyISAM引擎的一个特殊索引类型，主要用于地理空间数据类 型，通常使用较少</td></tr><tr><td>Full-text(全文 索引)</td><td>是一种通过建立倒排索引,快速匹配文档的方式。类似于 Lucene,Solr,ES</td></tr></tbody></table><p>不同存储索引对索引结构的支持情况</p><table><thead><tr><th>索引</th><th>InnoDB</th><th>MyISAM</th><th>Memory</th></tr></thead><tbody><tr><td>B+tree索引</td><td>支持</td><td>支持</td><td>支持</td></tr><tr><td>Hash 索引</td><td>不支持</td><td>不支持</td><td>支持</td></tr><tr><td>R-tree 索引</td><td>不支持</td><td>支持</td><td>不支持</td></tr><tr><td>Full-text</td><td>5.6版本之后支持</td><td>支持</td><td>不支持</td></tr></tbody></table><blockquote><p>不加说明默认所说的索引都是B+数结构组织的索引</p></blockquote><h3 id="二叉树">二叉树</h3><blockquote><p>以下内容涉及到数据结构，有数据结构基础的读者会更容易理解。</p></blockquote><p>缺点：顺序插入时，会形成一个链表，查询性能大大降低。大数据量情况下，层级较深，检索速度慢 。使用红黑树也会存在层级较深的问题。</p><h3 id="B-Tree与B-Tree">B-Tree与B+Tree</h3><p>B-Tree，B树是一种多叉路衡查找树，相对于二叉树，B树每个节点可以有多个分支，即多叉。以一颗最大度数（max-degree）为5(5阶)的b-tree为例，那这个B树每个节点最多存储4个key，5个指针</p><p><img src="https://s2.loli.net/2024/11/26/lBwy7UXRN35sjch.png" alt="100_演示图_02.png"></p><p>读者可以通过此网站观看B树数据插入的方式和节点的变化。<a href="https://www.cs.usfca.edu/~galles/visualization/BTree.html">B-Tree Visualization</a> 就会发现</p><ul><li>5阶的B树，每一个节点最多存储4个key，对应5个指针。</li><li>一旦节点存储的key数量到达5，就会裂变，中间元素向上分裂。</li><li>在B树中，非叶子节点和叶子节点都会存放数据。</li></ul><p>B+Tree是B-Tree的变种，我们以一颗最大度数（max-degree）为4（4阶）的b+tree为例，来看一下其结构示意图</p><p><img src="https://s2.loli.net/2024/11/26/5SQDnqfm8HbcEyr.png" alt="100_演示图_03.png"></p><p>绿色框框起来的部分，是索引部分，仅仅起到索引数据的作用，不存储数据。红色框框起来的部分，是数据存储部分，在其叶子节点中要存储具体的数据。  这样看来B+树和B-树有以下区别</p><ul><li>所有的数据都会出现在叶子节点。</li><li>叶子节点形成一个单向链表。</li><li>非叶子节点仅仅起到索引数据作用，具体的数据都是在叶子节点存放的。</li></ul><p>在MySQL中，对经典的B+Tree数据结构进行了优化，在原B+Tree的基础上，增加一个指向相邻叶子节点的链表指针，就形成了带有顺序指针的B+Tree，提高区间访问的性能，利于排序。如下图。</p><p><img src="https://s2.loli.net/2024/11/26/7ZJbL1KVn4f8tBG.png" alt="100_演示图_04.png"></p><h3 id="Hash">Hash</h3><p>概念：哈希索引就是采用一定的hash算法，将键值换算成新的hash值，映射到对应的槽位上，然后存储在hash表中。</p><p><img src="https://s2.loli.net/2024/11/26/pXyItfc4lT2AQvR.png" alt="100_演示图_05.png"></p><p>如果两个(或多个)键值，映射到一个相同的槽位上，他们就产生了hash冲突（也称为hash碰撞），可以通过链表来解决。</p><p><img src="https://s2.loli.net/2024/11/26/rO6wJW3sibhPHY1.png" alt="100_演示图_06.png"></p><p>特点</p><ul><li>Hash索引只能用于对等比较(=，in)，不支持范围查询（between，&gt;，&lt; ，…）</li><li>无法利用索引完成排序操作</li><li>查询效率高，通常(不存在hash冲突的情况)只需要一次检索就可以了，效率通常要高于B+tree索引</li></ul><p>存储引擎支持<br>在MySQL中，支持hash索引的是Memory存储引擎。 而InnoDB中具有自适应hash功能，hash索引是InnoDB存储引擎根据B+Tree索引在指定条件下<strong>自动构建</strong>的。</p><h2 id="索引分类">索引分类</h2><p>在MySQL数据库，将索引的具体类型主要分为以下几类：主键索引、唯一索引、常规索引、全文索引。</p><table><thead><tr><th>分类</th><th>含义</th><th>特点</th><th>关键字</th></tr></thead><tbody><tr><td>主键 索引</td><td>针对于表中主键创建的索引</td><td>默认自动创建, 只能 有一个</td><td>PRIMARY</td></tr><tr><td>唯一 索引</td><td>避免同一个表中某数据列中的值重复</td><td>可以有多个</td><td>UNIQUE</td></tr><tr><td>常规 索引</td><td>快速定位特定数据</td><td>可以有多个</td><td></td></tr><tr><td>全文 索引</td><td>全文索引查找的是文本中的关键词，而不是比 较索引中的值</td><td>可以有多个</td><td>FULLTEXT</td></tr></tbody></table><h3 id="聚集索引-二级索引">聚集索引&amp;二级索引</h3><p>在InnoDB存储引擎中，根据索引的存储形式，又可以分为以下两种</p><table><thead><tr><th>分类</th><th>含义</th><th>特点</th></tr></thead><tbody><tr><td>聚集索引(Clustered Index)</td><td>将数据存储与索引放到了一块，索引结构的叶子 节点保存了行数据</td><td>必须有,而且只 有一个</td></tr><tr><td>二级索引(Secondary Index)</td><td>将数据与索引分开存储，索引结构的叶子节点关 联的是对应的主键</td><td>可以存在多个</td></tr></tbody></table><p>聚集索引选取规则:</p><ul><li>如果存在主键，主键索引就是聚集索引。</li><li>如果不存在主键，将使用第一个唯一（UNIQUE）索引作为聚集索引。</li><li>如果表没有主键，或没有合适的唯一索引，则InnoDB会自动生成一个rowid作为隐藏的聚集索引。</li></ul><p>聚集索引和二级索引的具体结构如下：</p><p><img src="https://s2.loli.net/2024/11/26/ElsgkG3fOBTnoPV.png" alt="100_演示图_07.png"></p><p>聚集索引的叶子节点下挂的是这一行的数据 ,二级索引的叶子节点下挂的是该字段值对应的主键值.</p><p>其具体的查找过程如下</p><p><img src="https://s2.loli.net/2024/11/26/7X291gyBJqfj53e.png" alt="100_演示图_08.png"></p><ol><li>由于是根据name字段进行查询，所以先根据name='Arm’到name字段的二级索引中进行匹配查找。但是在二级索引中只能查找到 Arm 对应的主键值 10。</li><li>由于查询返回的数据是*，所以此时，还需要根据主键值10，到聚集索引中查找10对应的记录，最终找到10对应的行row。</li><li>最终拿到这一行的数据，直接返回即可。</li></ol><p><strong>回表查询</strong>： 这种<strong>先到二级索引中查找数据</strong>，找到主键值，然后<strong>再到聚集索引中根据主键值</strong>，获取数据的方式，就称之为回表查询。 由此我们可以推断，<strong>聚集索引搜索比二级索引搜索效率要高</strong>。</p><p>计算题：计算InnoDB主键索引的B+Tree高度。</p><p>查看答案</p><div class="hide-block"><button type="button" class="hide-button" style>查看答案</button><div class="hide-content"><p>解：设一行数据大小为1k，一页中可以存储16行这样的数据。InnoDB的指针占用6个字节的空间，主键即使为bigint，占用字节数为8。<br>当树的高度为2：n * 8 + (n + 1) * 6 = 16*1024 , 算出n约为 1170，得1171* 16 = 18736<br>也就是说，如果树的高度为2，则可以存储 18000 多条记录。</p></div></div><h2 id="索引语法">索引语法</h2><ol><li>查看索引</li></ol><p>语法：<code>show index from table_name;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 展示索引</span></span><br><span class="line"><span class="keyword">show</span> index <span class="keyword">from</span> tb_user;</span><br><span class="line"><span class="comment">-- 在linux中输出结果表格断行，建议末尾加上\G,其他情况的表格断行也可以使用</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/4aPLT5uwqbXyEzn.png" alt="002_存储索引_02.png"></p><ol start="2"><li>创建索引</li></ol><p>语法：<code>CREATE [ UNIQUE | FULLTEXT ] INDEX index_name ON table_name (index_col_name,... ) ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建一般索引</span></span><br><span class="line"><span class="keyword">create</span> index idx_user_name <span class="keyword">on</span> tb_user(name);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/tq8DZxeBIvc5FfL.png" alt="002_存储索引_03.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建唯一索引</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">unique</span> index idx_user_phone <span class="keyword">on</span> tb_user(phone);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/m74j3DMpszYdy6S.png" alt="002_存储索引_04.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建联合索引</span></span><br><span class="line"><span class="keyword">create</span> index idx_user_pro_age_sta <span class="keyword">on</span> tb_user(profession,age,status);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/EGKDjf1e2vgF8hq.png" alt="002_存储索引_05.png"></p><ol start="3"><li>删除索引</li></ol><p>语法：<code>DROP INDEX index_name ON table_name</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除索引</span></span><br><span class="line"><span class="keyword">drop</span> index idx_user_name <span class="keyword">on</span> tb_user(name);</span><br></pre></td></tr></table></figure><h2 id="SQL性能分析">SQL性能分析</h2><h3 id="SQL执行频率">SQL执行频率</h3><p>MySQL 客户端连接成功后，通过 show [session|global] status 命令可以提供服务器状态信息。通过如下指令，可以查看当前数据库的INSERT、UPDATE、DELETE、SELECT的访问频次</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- sql执行频率</span></span><br><span class="line"><span class="comment">-- session 是查看当前会话</span></span><br><span class="line"><span class="comment">-- global 是查询全局数据</span></span><br><span class="line"><span class="keyword">show</span> <span class="keyword">global</span> status <span class="keyword">like</span> <span class="string">&#x27;Com_______&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/qerfIgZlNWaAnPD.png" alt="003_SQL性能分析_01.png"></p><p>这其中<code>Com_delete</code>是删除次数 <code>Com_insert</code>是插入次数 <code>Com_select</code>是查询次数 <code>Com_update</code>是更新次数</p><blockquote><p>通过上述指令，我们可以查看到当前数据库到底是以查询为主，还是以增删改为主，从而为数据库优化提供参考依据。 如果是以增删改为主，我们可以考虑不对其进行索引的优化。 如果是以查询为主，那么就要考虑对数据库的索引进行优化了</p></blockquote><h3 id="慢查询日志">慢查询日志</h3><p>慢查询日志记录了所有执行时间超过指定参数（long_query_time，单位：秒，默认10秒）的所有SQL语句的日志。<br>MySQL的慢查询日志默认没有开启，我们可以查看一下系统变量 slow_query_log。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> variable <span class="keyword">like</span> &quot;slow_query_log&quot;</span><br><span class="line"><span class="comment">-- 结果为</span></span><br><span class="line"><span class="comment">-- +----------------+-------+</span></span><br><span class="line"><span class="comment">-- | Variable_name  | Value |</span></span><br><span class="line"><span class="comment">-- +----------------+-------+</span></span><br><span class="line"><span class="comment">-- | slow_query_log | OFF    |</span></span><br><span class="line"><span class="comment">-- +----------------+-------+</span></span><br></pre></td></tr></table></figure><p>在MySQL中慢查询默认关闭，如果要开启慢日志，需要先退出MySQL(<code>quit</code>)在MySQL的配置文件（/etc/my.cnf）中配置如下信息：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 开启MySQL慢日志查询开关</span></span><br><span class="line">slow_query_log<span class="operator">=</span><span class="number">1</span></span><br><span class="line"><span class="comment">-- 设置慢日志的时间为2秒，SQL语句执行时间超过2秒，就会视为慢查询，记录慢查询日志</span></span><br><span class="line">long_query_time<span class="operator">=</span><span class="number">2</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/X7mtJbciK8aWDwR.png" alt="003_SQL性能分析_02.png"></p><p>配置完毕之后，通过以下指令重新启动MySQL服务器进行测试，查看慢日志文件中记录的信息/var/lib/mysql/localhost-slow.log。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-- 重启MySQL服务器</span><br><span class="line">systemctl restart mysqld</span><br><span class="line">-- 其慢查询文件放在cd /var/lib/mysql 下，文件名为localhost-slow.log(我这里是hspEdu01-slow.log)</span><br></pre></td></tr></table></figure><p>再次查询后就会发现OFF变成了ON</p><p>这样当以后查询的时间超过2秒的时候，就会视为慢查询，然后记录在慢查询日志里，如下</p><p><img src="https://s2.loli.net/2024/11/26/VN1bIeY58jE2Jl3.png" alt="003_SQL性能分析_04.png"></p><h3 id="profile">profile</h3><p><code>show profiles</code> 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过have_profiling参数，能够看到当前MySQL是否支持profile操作</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看是否支持profile</span></span><br><span class="line"><span class="keyword">select</span> @<span class="variable">@have_profiling</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/w8oApP5kCujXniH.png" alt="003_SQL性能分析_05.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看profile是否开启</span></span><br><span class="line"><span class="keyword">select</span> @<span class="variable">@profiling</span>;</span><br><span class="line"><span class="comment">-- 结果</span></span><br><span class="line"><span class="comment">-- +-------------+</span></span><br><span class="line"><span class="comment">-- | @@profiling |</span></span><br><span class="line"><span class="comment">-- +-------------+</span></span><br><span class="line"><span class="comment">-- |           0 |</span></span><br><span class="line"><span class="comment">-- +-------------+</span></span><br></pre></td></tr></table></figure><p>可以看到MySQL支持profile操作但是没有开启,可以通过set语句在(session/global级别开启profiling)</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 开启profile</span></span><br><span class="line"><span class="keyword">set</span> profiling <span class="operator">=</span> <span class="number">1</span>;</span><br></pre></td></tr></table></figure><p>测试一下</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 测试</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> id <span class="operator">=</span><span class="number">1</span>;</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> name<span class="operator">=</span><span class="string">&#x27;白起&#x27;</span>;</span><br><span class="line"><span class="comment">-- 查看每一条SQL的耗时基本情况</span></span><br><span class="line"><span class="keyword">show</span> profiles ;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/k8TcEnhs6tdRpeo.png" alt="003_SQL性能分析_06.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看指定ID的耗时情况</span></span><br><span class="line"><span class="keyword">show</span> profile <span class="keyword">for</span> query <span class="number">55</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/D27WAfRiap5zSy6.png" alt="003_SQL性能分析_07.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看指定ID的占用CPU的情况</span></span><br><span class="line"><span class="keyword">show</span> profile cpu <span class="keyword">for</span> query <span class="number">92</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/8VhEsyrmHNwXKO1.png" alt="003_SQL性能分析_08.png"></p><h3 id="explain">explain</h3><p>EXPLAIN 或者 DESC命令获取 MySQL 如何执行 SELECT 语句的信息，包括在 SELECT 语句执行过程中表如何连接和连接的顺序。</p><p>语法</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 直接在select语句之前加上关键字 explain / desc</span></span><br><span class="line">EXPLAIN <span class="keyword">SELECT</span> 字段列表 <span class="keyword">FROM</span> 表名 <span class="keyword">WHERE</span> 条件 ;</span><br><span class="line"><span class="comment">-- 示例</span></span><br><span class="line"><span class="comment">-- 在语句前添加explain就行</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">1</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ES3yUGID4Jcd8iF.png" alt="003_SQL性能分析_09.png"></p><p>解释</p><table><thead><tr><th>字段</th><th>含义</th></tr></thead><tbody><tr><td>id</td><td>select查询的序列号，表示查询中执行select子句或者是操作表的顺序 (id相同，执行顺序从上到下；id不同，值越大，越先执行)。</td></tr><tr><td>select_type</td><td>表示 SELECT 的类型，常见的取值有 SIMPLE（简单表，即不使用表连接 或者子查询）、PRIMARY（主查询，即外层的查询）、 UNION（UNION 中的第二个或者后面的查询语句）、 SUBQUERY（SELECT/WHERE之后包含了子查询）等</td></tr><tr><td>type</td><td>表示连接类型，性能由好到差的连接类型为NULL、system、const、 eq_ref、ref、range、 index、all 。</td></tr><tr><td>possible_key</td><td>显示可能应用在这张表上的索引，一个或多个。</td></tr><tr><td>key</td><td>实际使用的索引，如果为NULL，则没有使用索引。</td></tr><tr><td>key_len</td><td>表示索引中使用的字节数， 该值为索引字段最大可能长度，并非实际使用长 度，在不损失精确性的前提下， 长度越短越好 。</td></tr><tr><td>rows</td><td>MySQL认为必须要执行查询的行数，在innodb引擎的表中，是一个估计值， 可能并不总是准确的。</td></tr><tr><td>filtered</td><td>表示返回结果的行数占需读取行数的百分比， filtered 的值越大越好。</td></tr></tbody></table><h2 id="索引使用">索引使用</h2><p>演示索引</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 演示</span></span><br><span class="line">explain <span class="keyword">select</span> s.<span class="operator">*</span>,c.<span class="operator">*</span> <span class="keyword">from</span> student s,course c,student_course sc <span class="keyword">where</span> s.id <span class="operator">=</span> sc.studentid <span class="keyword">and</span> c.id <span class="operator">=</span> sc.courseid;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/fcy6dRDePrOplZt.png" alt="003_SQL性能分析_10.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 嵌套语句的分析</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> student s <span class="keyword">where</span> s.id <span class="keyword">in</span> (</span><br><span class="line">    <span class="keyword">select</span> studentid <span class="keyword">from</span> student_course sc <span class="keyword">where</span> sc.courseid <span class="operator">=</span> (</span><br><span class="line">        <span class="keyword">select</span> id <span class="keyword">from</span> course c <span class="keyword">where</span> c.name <span class="operator">=</span> <span class="string">&#x27;MySQL&#x27;</span></span><br><span class="line">    )</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/rTy2sdWij8IHvRn.png" alt="003_SQL性能分析_11.png"></p><p>如果是数据量大的数据库，在查询的时候有索引和没有索引是两个效率，所以对于数据量大、经常被查询的表，创建索引是非常有效的方法。</p><h3 id="最左前缀法则">最左前缀法则</h3><p>如果索引了多列（联合索引），要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始，并且不跳过索引中的列。如果跳跃某一列，索引将会<strong>部分失效</strong>(后面的字段索引失效)。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询从索引的最左列开始，并且不跳过索引中的列</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> age <span class="operator">=</span> <span class="number">31</span> <span class="keyword">and</span> status <span class="operator">=</span> <span class="string">&#x27;0&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/q4gkK6H5IoUzPZb.png" alt="003_SQL性能分析_12.png"></p><p>讲解：假设存在一张tb_user 表，其中有一个联合索引，这个联合索引涉及到三个字段，顺序分别为：profession，age，status。对于最左前缀法则指的是，查询时，<strong>最左边的列</strong>，也就是profession<strong>必须存在</strong>，否则索引<strong>全部失效</strong>。而且中间不能跳过某一列，否则该列后面的字段索引将失效。  比如上面的在查询的时候只有<code>age</code>和<code>status</code> 没有<code>profession</code> 所以索引失效(NULL).</p><blockquote><p>注意 ： 最左前缀法则中指的最左边的列，是指在查询时，联合索引的最左边的字段(即是第一个字段)必须存在，与我们编写SQL时，条件编写的先后顺序无关。</p></blockquote><h3 id="范围查询">范围查询</h3><ol><li>联合索引中，出现范围查询，则范围查询右侧的列索引失效</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 范围查询</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span> <span class="keyword">and</span> age<span class="operator">&gt;</span><span class="number">30</span> <span class="keyword">and</span> status <span class="operator">=</span> <span class="string">&#x27;0&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/zkTKXrRZSCtyElf.png" alt="003_SQL性能分析_13.png"></p><p>当范围查询使用&gt; 或 &lt; 时，走联合索引了，但是索引的长度为49，就说明范围查询右边的status字段是没有走索引的。</p><p>在业务允许的情况下，尽可能的使用类似于 &gt;= 或 &lt;= 这类的范围查询，而避免使用 &gt; 或  &lt;.</p><ol start="2"><li>不要在索引列上进行运算操作，否则索引失效</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> <span class="built_in">substring</span>(phone,<span class="number">10</span>,<span class="number">2</span>) <span class="operator">=</span> <span class="string">&#x27;15&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/GfIDjSvUcKJ64qd.png" alt="003_SQL性能分析_14.png"></p><ol start="3"><li>字符串不加引号会失效:原因 <strong>存在隐式类型转换</strong></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> phone <span class="operator">=</span> <span class="number">17799990013</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/exET3cPQr4uYXI5.png" alt="003_SQL性能分析_15.png"></p><ol start="4"><li>头部模糊匹配会导致索引失效</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> profession <span class="keyword">like</span> <span class="string">&#x27;%工程&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/OgnzGJqHS1KZE78.png" alt="003_SQL性能分析_16.png"></p><ol start="5"><li>用or分割开的条件，如果or前的条件中的列有索引，而后面的列中没有索引，那么涉及的索引都不会被用到。</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">10</span> <span class="keyword">or</span> age <span class="operator">=</span> <span class="number">23</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/Khek5VsH41QGIgd.png" alt="003_SQL性能分析_17.png"></p><ol start="6"><li>当mysql评估使用索引比全表搜索慢，就不会使用索引</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> phone <span class="operator">&gt;=</span><span class="string">&#x27;17799990000&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/NUkL5yI4ZqFRb8G.png" alt="003_SQL性能分析_18.png"></p><ol start="7"><li>还有一种情况是使用<code>is null</code> 和<code>is not null</code> 是否走索引并不固定</li></ol><h3 id="SQL提示">SQL提示</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- SQL提示</span></span><br><span class="line"><span class="comment">-- 准备索引</span></span><br><span class="line"><span class="keyword">create</span> index idx_user_pro <span class="keyword">on</span> tb_user(profession);</span><br><span class="line"><span class="comment">-- 一般情况下此SQL语句使用的索引</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/9dph53gMBIrGNQX.png" alt="003_SQL性能分析_19.png"></p><p>SQL提示，是优化数据库的一个重要手段，简单来说，就是在SQL语句中加入一些人为的提示(指定MySQL使用哪些索引)来达到优化操作的目的。</p><ol><li>建议MySQL使用指定索引： <code>use index;</code> 有可能MySQL不接受</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 使用单列索引 某些情况下mysql可能不接受</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user use index(idx_user_pro) <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/SU2WMLKhZTbVzHx.png" alt="003_SQL性能分析_20.png"></p><ol start="2"><li>忽略指定索引：<code>ignore index;</code></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 忽略某个索引</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user ignore index(idx_user_pro) <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/BMSYIK9u8k1iC4D.png" alt="003_SQL性能分析_21.png"></p><ol start="3"><li>强制使用指定索引：<code>force index;</code></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 强制使用某个索引</span></span><br><span class="line">explain <span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user force index(idx_user_pro) <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span>;</span><br></pre></td></tr></table></figure><h3 id="覆盖索引">覆盖索引</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询使用了索引，并且需要返回的列，在该索引中已经全部能够找到。也尽量减少使用select *</span></span><br><span class="line">explain <span class="keyword">select</span> id,profession,age,status,name <span class="keyword">from</span> tb_user <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span> <span class="keyword">and</span> age <span class="operator">=</span> <span class="number">31</span> <span class="keyword">and</span> status <span class="operator">=</span> <span class="string">&#x27;0&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/Wn23oEkjlsDqdPM.png" alt="003_SQL性能分析_22.png"></p><p>其中我们重点关注<code>Extra</code></p><table><thead><tr><th>Extra</th><th>含义</th></tr></thead><tbody><tr><td>Using where; Using Index</td><td>查找使用了索引，但是需要的数据都在索引列中能找到，所以不需 要回表查询数据</td></tr><tr><td>Using index condition</td><td>查找使用了索引，但是需要回表查询数据</td></tr></tbody></table><p>所以当我们查询返回的数据在 id、profession、age、status 之中，则直接走二级索引直接返回数据了。 如果超出这个范围，就需要拿到主键id，再去扫描聚集索引，再获取额外的数据了，这个过程就是回表。 而我们如果一直使用select * 查询返回所有字段值，很容易就会造成回表查询（除非是根据主键查询，此时只会扫描聚集索引），所以不建议使用select * 进行全字段查询。</p><p>演示覆盖索引与回表查询</p><p><img src="https://s2.loli.net/2024/11/26/lO4uocK1yfkV3jx.png" alt="100_演示图_09.png"></p><p>其中id是主键，是一个聚集索引。 name字段建立了普通索引，是一个二级索引（辅助索引）。</p><p><img src="https://s2.loli.net/2024/11/26/tAr8YFsZHLbvenU.png" alt="100_演示图_10.png"></p><p>根据id查询，直接走聚集索引查询，一次索引扫描，直接返回数据，性能高。</p><p><img src="https://s2.loli.net/2024/11/26/Gr2doMCASYqgmNz.png" alt="100_演示图_11.png"></p><p>虽然是根据name字段查询，查询二级索引，但是由于查询返回在字段为 id，name，在name的二级索<br>引中，这两个值都是可以直接获取到的，因为覆盖索引，所以不需要回表查询，性能高。</p><p><img src="https://s2.loli.net/2024/11/26/Hyk5LjU2K9IzAim.png" alt="100_演示图_12.png"></p><p>由于在name的二级索引中，不包含gender，所以，需要两次索引扫描，也就是需要回表查询，性能相对较差一点。</p><h3 id="前缀索引">前缀索引</h3><p>当字段类型为字符串（varchar，text，longtext等）时，有时候需要索引很长的字符串，这会让索引变得很大，查询时，浪费大量的磁盘IO， 影响查询效率。此时可以只将字符串的一部分前缀，建立索引，这样可以大大节约索引空间，从而提高索引效率。</p><p>语法:<code>create index idx_xxxx on table_name(column(n)) ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建前缀索引</span></span><br><span class="line"><span class="keyword">create</span> index idx_email_5 <span class="keyword">on</span> tb_user(email(<span class="number">5</span>));</span><br></pre></td></tr></table></figure><p><strong>前缀长度</strong>：可以根据索引的选择性来决定，而选择性是指不重复的索引值（基数）和数据表的记录总数的比值，索引选择性越高则查询效率越高， 唯一索引的选择性是1，这是最好的索引选择性，性能也是最好的。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 选择性 当选择性趋于1(也就是唯一索引)的时候效率最高</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">count</span>(<span class="keyword">distinct</span> <span class="built_in">substring</span>(email,<span class="number">1</span>,<span class="number">10</span>))<span class="operator">/</span><span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> tb_user;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/6ln1rRwVsoSvjyK.png" alt="003_SQL性能分析_23.png"></p><p>展示索引</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 展示索引</span></span><br><span class="line"><span class="keyword">show</span> index <span class="keyword">from</span> tb_user;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/rGiv74XynOIWP3T.png" alt="003_SQL性能分析_24.png"></p><p>前缀索引的查询流程</p><p><img src="https://s2.loli.net/2024/11/26/At9TiYkLUS5fmgc.png" alt="100_演示图_13.png"></p><h3 id="单列索引与联合索引">单列索引与联合索引</h3><p>单列索引：一个索引只包含单个列；联合索引：一个索引包含多个列。</p><p>在业务场景中，如果存在多个查询条件，考虑针对于查询字段建立索引时，建议建立联合索引，而非单列索引。</p><h3 id="索引设置原则">索引设置原则</h3><ol><li>针对于数据量较大，且查询比较频繁的表建立索引。</li><li>针对于常作为查询条件（where）、排序（order by）、分组（group by）操作的字段建立索<br>引。</li><li>尽量选择区分度高的列作为索引，尽量建立唯一索引，区分度越高，使用索引的效率越高。</li><li>如果是字符串类型的字段，字段的长度较长，可以针对于字段的特点，建立前缀索引。</li><li>尽量使用联合索引，减少单列索引，查询时，联合索引很多时候可以覆盖索引，节省存储空间，<br>避免回表，提高查询效率。</li><li>要控制索引的数量，索引并不是多多益善，索引越多，维护索引结构的代价也就越大，会影响增<br>删改的效率。</li><li>如果索引列不能存储NULL值，请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含<br>NULL值时，它可以更好地确定哪个索引最有效地用于查询。</li></ol><hr><h1>SQL优化</h1><h2 id="插入优化">插入优化</h2><p>如果我们需要一次性往数据库表中插入多条记录，可以从以下三个方面进行优化。</p><ol><li>使用批量插入</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 优化前</span></span><br><span class="line"><span class="keyword">insert into</span> tb_test <span class="keyword">values</span>(<span class="number">1</span>,<span class="string">&#x27;tom&#x27;</span>);</span><br><span class="line"><span class="keyword">insert into</span> tb_test <span class="keyword">values</span>(<span class="number">2</span>,<span class="string">&#x27;cat&#x27;</span>);</span><br><span class="line"><span class="keyword">insert into</span> tb_test <span class="keyword">values</span>(<span class="number">3</span>,<span class="string">&#x27;jerry&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 优化后</span></span><br><span class="line"><span class="keyword">Insert into</span> tb_test <span class="keyword">values</span>(<span class="number">1</span>,<span class="string">&#x27;Tom&#x27;</span>),(<span class="number">2</span>,<span class="string">&#x27;Cat&#x27;</span>),(<span class="number">3</span>,<span class="string">&#x27;Jerry&#x27;</span>);</span><br></pre></td></tr></table></figure><ol start="2"><li>使用事务(设置为手动提交)</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">start</span> transaction;</span><br><span class="line"><span class="keyword">insert into</span> tb_test <span class="keyword">values</span>(<span class="number">1</span>,<span class="string">&#x27;Tom&#x27;</span>),(<span class="number">2</span>,<span class="string">&#x27;Cat&#x27;</span>),(<span class="number">3</span>,<span class="string">&#x27;Jerry&#x27;</span>);</span><br><span class="line"><span class="keyword">insert into</span> tb_test <span class="keyword">values</span>(<span class="number">4</span>,<span class="string">&#x27;Tom&#x27;</span>),(<span class="number">5</span>,<span class="string">&#x27;Cat&#x27;</span>),(<span class="number">6</span>,<span class="string">&#x27;Jerry&#x27;</span>);</span><br><span class="line"><span class="keyword">insert into</span> tb_test <span class="keyword">values</span>(<span class="number">7</span>,<span class="string">&#x27;Tom&#x27;</span>),(<span class="number">8</span>,<span class="string">&#x27;Cat&#x27;</span>),(<span class="number">9</span>,<span class="string">&#x27;Jerry&#x27;</span>);</span><br><span class="line"><span class="keyword">commit</span>;</span><br></pre></td></tr></table></figure><ol start="3"><li>主键顺序插入</li></ol><p>主键顺序插入 : 1 2 3 4 5 7 8 9 15 21 88 89  效率要高于乱序</p><ol start="4"><li>大批量数据插入(万级别)</li></ol><p>使用MySQL的load指令，也就是读取sql文件。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">-- 1. 客户端连接服务端时，加上参数 -–local-infile</span><br><span class="line">mysql –-local-infile -u root -p</span><br><span class="line">-- 2. 设置全局参数local_infile为1，开启从本地加载文件导入数据的开关</span><br><span class="line">set global local_infile = 1;</span><br><span class="line">-- 3. 执行load指令将准备好的数据，加载到表结构中</span><br><span class="line">load data local infile &#x27;/root/sql1.sql(数据的路径)&#x27; into table tb_user(指定的表) fields terminated by &#x27;,&#x27; lines terminated by &#x27;\n&#x27; ; -- 读取数据时以逗号为间隔读取单个数据，当读取到\n自动换行。</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/nKyNkxEVT27wIqR.png" alt="003_SQL性能分析_25.png"></p><h2 id="主键优化">主键优化</h2><p>InnoDB中数据的组织方式：在InnoDB存储引擎中，表数据都是根据主键顺序组织存放的，这种存储方式的表称为索引组织表</p><p>见图<strong>100_演示图_04</strong> 其逻辑结构图见图 <strong>001_存储引擎_06</strong></p><p>在InnoDB引擎中，数据行是记录在逻辑结构 page 页中的，而每一个页的大小是固定的，默认16K。那也就意味着， 一个页中所存储的行也是有限的，如果插入的数据行row在该页存储不小，将会存储到下一个页中，页与页之间会通过指针连接。</p><p><strong>页分裂</strong>：页可以为空，也可以填充一半，也可以填充100%。每个页包含了2-N行数据(如果一行数据过大，会行溢出)，根据主键排列。</p><p>此处留空:<strong>做三个manim动画演示顺序、乱序、页合并的步骤</strong></p><p><strong>顺序插入</strong>步骤如下</p><ol><li>从磁盘中申请页， 主键顺序插入</li><li>第一个页没有满，继续往第一页插入</li><li>当第一个也写满之后，再写入第二个页，页与页之间会通过指针连接</li><li>当第二页写满了，再往第三页写入</li></ol><p><strong>乱序插入</strong>步骤如下</p><ol start="0"><li>假如1、2页已满</li><li>再插入一个id为1、2页之中的数据，会直接开辟一个页(页3).</li><li>然后将1页后一半的数据放在刚开辟的页，再插入数据。</li><li>然后设置链表指针，为1-&gt;3-&gt;2</li></ol><p><strong>页合并</strong>：</p><ol><li>持续删除某个页的记录，看是否达到MERGE_THRESHOLD（默认为页的50%)</li><li>如果达到界限，InnoDB会开始寻找最靠近的页（前或后）看看是否可以将两个页合并以优化空间使用。</li><li>然后删除数据，并将页合并之后，如果再次插入新的数据，就会在后面的页面添加</li></ol><blockquote><p>MERGE_THRESHOLD：合并页的阈值，可以自己设置，在创建表或者创建索引时指定</p></blockquote><p><strong>索引设置原则</strong></p><ul><li>满足业务需求的情况下，尽量降低主键的长度。</li><li>插入数据时，尽量选择顺序插入，选择使用AUTO_INCREMENT自增主键。</li><li>尽量不要使用UUID做主键或者是其他自然主键，如身份证号。</li><li>业务操作时，避免对主键的修改</li></ul><h2 id="order-by优化">order by优化</h2><p>MySQL的排序，有两种方式：</p><ol><li><p><strong>Using filesort</strong> : 通过表的索引或全表扫描，读取满足条件的数据行，然后在排序缓冲区sortbuffer中完成排序操作，所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。</p></li><li><p><strong>Using index</strong> : 通过有序索引顺序扫描直接返回有序数据，这种情况即为 using index，不需要额外排序，操作效率高。</p></li></ol><p>对于以上的两种排序方式，Using index的性能高，而Using filesort的性能低，我们在优化排序操作时，尽量要优化为 Using index。</p><p>测试</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- sql优化，由于字段没有索引，所以用filesort</span></span><br><span class="line">explain <span class="keyword">select</span> id, age,phone <span class="keyword">from</span> tb_user <span class="keyword">order</span> <span class="keyword">by</span> age;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/QL4mE81asPrDnwG.png" alt="004_SQL优化_01.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建索引</span></span><br><span class="line"><span class="keyword">create</span> index idx_user_phone <span class="keyword">on</span> tb_user(phone);</span><br><span class="line">explain <span class="keyword">select</span> id,age,phone <span class="keyword">from</span> tb_user <span class="keyword">order</span> <span class="keyword">by</span> phone,age;</span><br></pre></td></tr></table></figure><p>建立索引之后，再次进行排序查询，就由原来的Using filesort， 变为了 Using index，性能就是比较高的了。</p><p>排序时,也需要满足<strong>最左前缀法则</strong>,否则也会出现 filesort。</p><p>order by<strong>优化原则</strong></p><ol><li>根据排序字段建立合适的索引，多字段排序时，也遵循最左前缀法则。</li><li>尽量使用覆盖索引。</li><li>多字段排序, 一个升序一个降序，此时需要注意联合索引在创建时的规则（ASC/DESC）。</li><li>如果不可避免的出现filesort，大数据量排序时，可以适当增大排序缓冲区大小 sort_buffer_size(默认256k)。</li></ol><h2 id="group-by优化">group by优化</h2><p>没有索引情况下的查询</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 没有索引情况下的查询</span></span><br><span class="line">explain <span class="keyword">select</span> profession,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> tb_user <span class="keyword">group</span> <span class="keyword">by</span> profession;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/J7disnyOeESvgR5.png" alt="004_SQL优化_02.png"></p><p>对于分组操作，在联合索引中，也是符合<strong>最左前缀法则</strong>的。</p><p>有索引情况下的查询</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建联合索引之后再次执行</span></span><br><span class="line"><span class="keyword">create</span> index idx_user_pro_age_sta <span class="keyword">on</span> tb_user(profession,age,status);</span><br><span class="line">explain <span class="keyword">select</span> profession,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> tb_user <span class="keyword">group</span> <span class="keyword">by</span> profession;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ZjixyRaB5p8tmEk.png" alt="004_SQL优化_03.png"></p><p><strong>group by优化原则</strong></p><ol><li>在分组操作时，可以通过索引来提高效率。</li><li>分组操作时，索引的使用也是满足最左前缀法则的。</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 在给联合索引命名时注意从左到右命名，方便查看是否符合最左前缀法则，如下</span></span><br><span class="line">explain <span class="keyword">select</span> age,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> tb_user <span class="keyword">where</span> profession <span class="operator">=</span> <span class="string">&#x27;软件工程&#x27;</span> <span class="keyword">group</span> <span class="keyword">by</span> age;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/XxwmjUiyza68gKQ.png" alt="004_SQL优化_04.png"></p><h2 id="limit优化">limit优化</h2><p>在数据量比较大时，如果进行limit分页查询，在查询时，越往后，分页查询效率越低。</p><p>优化思路: 一般分页查询时，通过创建 覆盖索引 能够比较好地提高性能，可以通过覆盖索引加子查询形式进行优化。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 优化前</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user <span class="keyword">order</span> <span class="keyword">by</span> id limit <span class="number">10</span>,<span class="number">10</span>;</span><br><span class="line"><span class="comment">-- 优化后，页数越多优化效果越明显</span></span><br><span class="line">explain <span class="keyword">select</span> s.<span class="operator">*</span> <span class="keyword">from</span> tb_user s,(<span class="keyword">select</span> id <span class="keyword">from</span> tb_user <span class="keyword">order</span> <span class="keyword">by</span> id limit <span class="number">10</span>,<span class="number">10</span>) a <span class="keyword">where</span> s.id <span class="operator">=</span> a.id;</span><br></pre></td></tr></table></figure><h2 id="count优化">count优化</h2><p>在之前的测试中，我们发现，如果数据量很大，在执行count操作时，是非常耗时的。</p><ul><li><p>MyISAM 引擎把一个表的总行数存在了磁盘上，因此执行 count(*) 的时候会直接返回这个数，效率很高； 但是如果是带条件的count，MyISAM也慢。</p></li><li><p>InnoDB 引擎就麻烦了，它执行 count(*) 的时候，需要把数据一行一行地从引擎里面读出来，然后累积计数。</p></li></ul><p>如果说要大幅度提升InnoDB表的count效率，主要的优化思路：自己计数(可以借助于redis这样的数据库进行,但是如果是带条件的count又比较麻烦了)。</p><p>count的用法</p><table><thead><tr><th>count用 法</th><th>含义</th></tr></thead><tbody><tr><td>count(主 键)</td><td>InnoDB 引擎会遍历整张表，把每一行的 主键id 值都取出来，返回给服务层。 服务层拿到主键后，直接按行进行累加(主键不可能为null)</td></tr><tr><td>count(字 段)</td><td>没有not null 约束 : InnoDB 引擎会遍历整张表把每一行的字段值都取出 来，返回给服务层，服务层判断是否为null，不为null，计数累加。 有not null 约束：InnoDB 引擎会遍历整张表把每一行的字段值都取出来，返 回给服务层，直接按行进行累加。</td></tr><tr><td>count(数 字)</td><td>InnoDB 引擎遍历整张表，但不取值。服务层对于返回的每一行，放一个数字“1” 进去，直接按行进行累加。</td></tr><tr><td>count(*)</td><td>InnoDB引擎并不会把全部字段取出来，而是专门做了优化，不取值，服务层直接 按行进行累加。</td></tr></tbody></table><blockquote><p>按照效率排序的话，count(字段) &lt; count(主键 id) &lt; count(1) ≈ count(*)，所以尽量使用 count(*)。</p></blockquote><h2 id="update优化">update优化</h2><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">update</span> course <span class="keyword">set</span> name <span class="operator">=</span> <span class="string">&#x27;javaEE&#x27;</span> <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">1</span>;</span><br></pre></td></tr></table></figure><p>当我们在执行删除的SQL语句时，会锁定id为1这一行的数据，然后事务提交之后，行锁释放</p><p>当我们在执行如下SQL时</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">update</span> course <span class="keyword">set</span> name <span class="operator">=</span> <span class="string">&#x27;SpringBoot&#x27;</span> <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;PHP&#x27;</span> ;</span><br></pre></td></tr></table></figure><p>当我们开启多个事务，在执行上述的SQL时，我们发现行锁升级为了表锁。 导致该update语句的性能大大降低。</p><blockquote><p>InnoDB的行锁是针对索引加的锁，不是针对记录加的锁 ,并且该索引不能失效，否则会从行锁升级为表锁 。</p></blockquote><h1>视图</h1><h2 id="语法-v2">语法</h2><p>视图（View）是一种虚拟存在的表。视图中的数据并不在数据库中实际存在，行和列数据来自定义视图的查询中使用的表，并且是在使用视图时动态生成的。<br>通俗的讲，视图只保存了查询的SQL逻辑，不保存查询结果。所以我们在创建视图的时候，主要的工作就落在创建这条SQL查询语句上。</p><ol><li>创建视图</li></ol><p>语法：<code>CREATE [OR REPLACE] VIEW 视图名称[(列名列表)] AS SELECT语句 [ WITH [CASCADED | LOCAL ] CHECK OPTION ]  ;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建视图 会生成一个视图的文件夹，里面存放视图</span></span><br><span class="line"><span class="comment">-- or replace 是如果有就覆盖</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">or</span> replace <span class="keyword">view</span> stu_v_1 <span class="keyword">as</span> <span class="keyword">select</span> id,name <span class="keyword">from</span> student <span class="keyword">where</span> id <span class="operator">&lt;=</span><span class="number">10</span>;</span><br></pre></td></tr></table></figure><ol start="2"><li>查询视图</li></ol><p>语法：<code>查看创建视图语句：SHOW CREATE VIEW 视图名称;  查看视图数据：SELECT * FROM 视图名称 ...... ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询创建视图语句</span></span><br><span class="line"><span class="keyword">show</span> <span class="keyword">create</span> <span class="keyword">view</span> stu_v_1;</span><br><span class="line"><span class="comment">-- 查看视图数据</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> stu_v_1;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/Sbg6XFJ5inM3VNc.png" alt="005_视图_01.png"></p><ol start="3"><li>修改视图</li></ol><p>语法：<code>方式一：CREATE [OR REPLACE] VIEW 视图名称[(列名列表)] AS SELECT语句 [ WITH[ CASCADED | LOCAL ] CHECK OPTION ]; 方式二：ALTER VIEW 视图名称[(列名列表)] AS SELECT语句 [ WITH [ CASCADED |LOCAL ] CHECK OPTION ]  ;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 修改视图</span></span><br><span class="line"><span class="comment">-- 方式1</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">or</span> replace <span class="keyword">view</span> stu_v_1 <span class="keyword">as</span> <span class="keyword">select</span> id,name,<span class="keyword">no</span> <span class="keyword">from</span> student <span class="keyword">where</span> id <span class="operator">&lt;=</span><span class="number">10</span>;</span><br><span class="line"><span class="comment">-- 方式2</span></span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">view</span> stu_v_1 <span class="keyword">as</span> <span class="keyword">select</span> id,name <span class="keyword">from</span> student <span class="keyword">where</span> id <span class="operator">&lt;=</span><span class="number">10</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/kBOWxVqrRSPl4bH.png" alt="005_视图_02.png"></p><ol start="4"><li>删除视图</li></ol><p>语法：<code>DROP VIEW [IF EXISTS] 视图名称 [,视图名称] ...  ;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除视图</span></span><br><span class="line"><span class="keyword">drop</span> <span class="keyword">view</span> if <span class="keyword">exists</span> stu_v_1;</span><br></pre></td></tr></table></figure><h2 id="视图检查">视图检查</h2><p>当使用WITH CHECK OPTION子句创建视图时，MySQL会通过视图检查正在更改的每个行，例如 插入，更新，删除，以使其符合视图的定义。 MySQL允许基于另一个视图创建视图，它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围，mysql提供了两个选项： CASCADED 和 LOCAL，默认值为 CASCADED 。</p><ol><li><p>CASCADED(级联)<br>比如，v2视图是基于v1视图的，如果在v2视图创建的时候指定了检查选项为 cascaded，但是v1图创建时未指定检查选项。 则在执行检查时，不仅会检查v2，还会级联检查v2的关联视图v1。</p></li><li><p>LOCAL(本地)</p><p>比如，v2视图是基于v1视图的，如果在v2视图创建的时候指定了检查选项为 local ，但是v1视图创<br>建时未指定检查选项。 则在执行检查时，知会检查v2，不会检查v2的关联视图v1。</p></li></ol><h2 id="视图更新">视图更新</h2><p>要使视图可更新，视图中的行与基础表中的行之间必须存在一对一的关系。如果视图包含以下任何一<br>项，则该视图不可更新：</p><ol><li><p>聚合函数或窗口函数（SUM()、 MIN()、 MAX()、 COUNT()等）</p></li><li><p>DISTINCT</p></li><li><p>GROUP BY</p></li><li><p>HAVING</p></li><li><p>UNION 或者 UNION</p></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 视图的更新和作用</span></span><br><span class="line"><span class="comment">-- 前提：视图中的行与基础表中的行之间必须存在一一对应的关系。</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">view</span> stu_v_count <span class="keyword">as</span> <span class="keyword">select</span> <span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> student;</span><br><span class="line"><span class="keyword">insert into</span> stu_v_count <span class="keyword">values</span>(<span class="number">10</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/IAPDmJVkQYCOn1N.png" alt="005_视图_05.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建一个视图</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">or</span> replace <span class="keyword">view</span> stu_v_1 <span class="keyword">as</span> <span class="keyword">select</span> id,name <span class="keyword">from</span> student <span class="keyword">where</span> id <span class="operator">&lt;=</span><span class="number">20</span> <span class="keyword">with</span> <span class="keyword">cascaded</span> <span class="keyword">check</span> option ;</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> learning.stu_v_1;</span><br><span class="line"><span class="keyword">insert into</span> learning.stu_v_1 <span class="keyword">values</span>(<span class="number">6</span>,<span class="string">&#x27;Tom&#x27;</span>);<span class="comment">-- 视图本身不能插入数据，会将数据插入原来的表中</span></span><br><span class="line"><span class="comment">-- 检查30&gt;20 所以报错</span></span><br><span class="line"><span class="keyword">insert into</span> learning.stu_v_1 <span class="keyword">values</span>(<span class="number">30</span>,<span class="string">&#x27;Tom&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/X4s9muVaWDlBnRj.png" alt="005_视图_03.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 基于视图创建视图</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">or</span> replace <span class="keyword">view</span> stu_v_2 <span class="keyword">as</span> <span class="keyword">select</span> id,name <span class="keyword">from</span> learning.stu_v_1 <span class="keyword">where</span> id<span class="operator">&lt;=</span><span class="number">10</span>;</span><br><span class="line"><span class="comment">-- 测试插入数据</span></span><br><span class="line"><span class="keyword">insert into</span> stu_v_2 <span class="keyword">values</span>(<span class="number">18</span>,<span class="string">&#x27;Jerry&#x27;</span>);</span><br><span class="line"><span class="comment">-- 也就是说，如果基于视图创建视图但不添加检查选项时，就会依赖于父视图进行检查。</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/casGbjU4vwHP3Oi.png" alt="005_视图_04.png"></p><p><strong>视图的优点</strong></p><ol><li><strong>简单</strong>：视图不仅可以简化用户对数据的理解，也可以简化他们的操作。那些被经常使用的查询可以被定义为视图，从而使得用户不必为以后的操作每次指定全部的条件。</li><li><strong>安全</strong>：数据库可以授权，但不能授权到数据库特定行和特定的列上。通过视图用户只能查询和修改他们所能见到的数据</li><li><strong>数据独立</strong>：视图可帮助用户屏蔽真实表结构变化带来的影响。</li></ol><h2 id="视图的应用">视图的应用</h2><p>举例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 视图有点像是定制化的备份</span></span><br><span class="line"><span class="comment">-- 案例</span></span><br><span class="line"><span class="comment">-- 屏蔽手机号和邮箱</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">view</span> tb_user_view <span class="keyword">as</span> <span class="keyword">select</span> id,name,profession,age,gender,status,createtime <span class="keyword">from</span> tb_user;</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_user_view;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/wgmxi9zOG2rIPAn.png" alt="005_视图_06.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 通过视图实现三表联查</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">view</span> tb_stu_course_view <span class="keyword">as</span> <span class="keyword">select</span> s.name student_name,s.no student_no,c.name course_name <span class="keyword">from</span> student s,student_course sc,course c <span class="keyword">where</span> s.id <span class="operator">=</span> sc.studentid <span class="keyword">and</span> sc.courseid <span class="operator">=</span> c.id;</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> tb_stu_course_view;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/79g5UMTRO3EHatp.png" alt="005_视图_07.png"></p><h1>存储过程</h1><p>存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合，调用存储过程可以简化应用开发人员的很多工作，减少数据在数据库和应用服务器之间的传输，对于提高数据处理的效率是有好处的。<br>存储过程思想上很简单，就是数据库 SQL 语言层面的代码封装与重用</p><p>特点：</p><ol><li><p>封装，复用。可以把某一业务SQL封装在存储过程中，需要用到的时候直接调用即可。</p></li><li><p>可以接收参数，也可以返回数据。在存储过程中，可以传递参数，也可以接收返回值。</p></li><li><p>减少网络交互，效率提升。如果涉及到多条SQL，每执行一次都是一次网络传输。 而如果封装在存储过程中，我们只需要网络交互一次可能就可以了。</p></li><li><p>创建存储过程</p></li></ol><p>语法：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> 存储过程名称 ([ 参数列表 ])</span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"><span class="comment">-- SQL语句</span></span><br><span class="line"><span class="keyword">END</span> ;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 存储过程</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p1()</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">select</span> <span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> student;</span><br><span class="line"><span class="keyword">end</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/TWOvLQjxdeamCog.png" alt="006_储存过程_01.png"></p><ol start="2"><li>调用存储过程</li></ol><p>语法：<code>CALL 名称 ([ 参数 ]);  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 调用</span></span><br><span class="line"><span class="keyword">call</span> p1();</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/PLz8hEqwNHGnSUJ.png" alt="006_储存过程_02.png"></p><ol start="3"><li>查看存储过程</li></ol><p>语法：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="operator">*</span> <span class="keyword">FROM</span> INFORMATION_SCHEMA.ROUTINES <span class="keyword">WHERE</span> ROUTINE_SCHEMA <span class="operator">=</span> <span class="string">&#x27;xxx&#x27;</span>; <span class="comment">-- 查询指定数据库的存储过程及状态信息</span></span><br><span class="line"><span class="keyword">SHOW</span> <span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> 存储过程名称 ; <span class="comment">-- 查询某个存储过程的定义</span></span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看数据库的存储过程</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> information_schema.ROUTINES <span class="keyword">where</span> ROUTINE_SCHEMA <span class="operator">=</span> <span class="string">&#x27;learning&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/hlkrDbZH1gUTOiQ.png" alt="006_储存过程_03.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看存储过程的创建语句</span></span><br><span class="line"><span class="keyword">show</span> <span class="keyword">create</span> <span class="keyword">procedure</span> p1;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/miUKeBIfbs3CRW9.png" alt="006_储存过程_04.png"></p><ol start="4"><li>删除存储过程</li></ol><p>语法：<code>DROP PROCEDURE [ IF EXISTS ] 存储过程名称;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除存储过程</span></span><br><span class="line"><span class="keyword">drop</span> <span class="keyword">procedure</span> if <span class="keyword">exists</span> p1;</span><br></pre></td></tr></table></figure><blockquote><p>注意:在命令行中(Linux使用MySQL)，执行创建存储过程的SQL时，需要通过关键字 delimiter 指定SQL语句的结束符。</p></blockquote><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">delimiter $$</span><br><span class="line">create procedure p1()</span><br><span class="line">begin</span><br><span class="line">    select count(*) from student;</span><br><span class="line"><span class="meta prompt_">end$</span><span class="language-bash">$</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/CeoEHSvudahNsfA.png" alt="006_储存过程_05.png"></p><h2 id="变量">变量</h2><h3 id="系统变量">系统变量</h3><p>系统变量是MySQL服务器提供，不是用户定义的，属于服务器层面。分为全局变量（GLOBAL）、会话变量（SESSION）。</p><ol><li>查看系统变量</li></ol><p>语法:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SHOW</span> [ SESSION <span class="operator">|</span> <span class="keyword">GLOBAL</span> ] VARIABLES ; <span class="comment">-- 查看所有系统变量</span></span><br><span class="line"><span class="keyword">SHOW</span> [ SESSION <span class="operator">|</span> <span class="keyword">GLOBAL</span> ] VARIABLES <span class="keyword">LIKE</span> <span class="string">&#x27;......&#x27;</span>; <span class="comment">-- 可以通过LIKE模糊匹配方式查找变量</span></span><br><span class="line"><span class="keyword">SELECT</span> @@[SESSION <span class="operator">|</span> <span class="keyword">GLOBAL</span>] 系统变量名; <span class="comment">-- 查看指定变量的值</span></span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看系统变量</span></span><br><span class="line"><span class="keyword">show</span> session variables ;</span><br><span class="line"><span class="comment">-- 模糊匹配</span></span><br><span class="line"><span class="keyword">show</span> <span class="keyword">global</span> variables <span class="keyword">like</span> <span class="string">&#x27;auto%&#x27;</span>;</span><br><span class="line"><span class="comment">-- 查看某一个变量</span></span><br><span class="line"><span class="keyword">select</span> @<span class="variable">@autocommit</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/VoETYOUq63tmgPW.png" alt="007_变量_01.png"></p><ol start="2"><li>设置系统变量</li></ol><p>语法:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SET</span> [ SESSION <span class="operator">|</span> <span class="keyword">GLOBAL</span> ] 系统变量名 <span class="operator">=</span> 值 ;</span><br><span class="line"><span class="keyword">SET</span> @@[SESSION <span class="operator">|</span> <span class="keyword">GLOBAL</span>]系统变量名 <span class="operator">=</span> 值 ;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 设置系统变量</span></span><br><span class="line"><span class="keyword">set</span> session autocommit <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="comment">-- mysql服务重新启动后所设置的全局参数会失效，如果要永久改变需要在/etc/my.cnf中配置</span></span><br></pre></td></tr></table></figure><blockquote><p>概念：</p><ol><li>全局变量(GLOBAL): 全局变量针对于所有的会话。</li><li>会话变量(SESSION): 会话变量针对于单个会话，在另外一个会话窗口就不生效了。</li><li>未指定session或者global的时候默认是session</li></ol></blockquote><h3 id="用户定义变量">用户定义变量</h3><p>用户定义变量：是用户根据需要自己定义的变量，用户变量不用提前声明，在用的时候直接用 “@变量名” 使用就可以。其作用域为当前连接。</p><ol><li>赋值</li></ol><p>语法1</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SET</span> <span class="variable">@var_name</span> <span class="operator">=</span> expr [, <span class="variable">@var_name</span> <span class="operator">=</span> expr] ... ;</span><br><span class="line"><span class="keyword">SET</span> <span class="variable">@var_name</span> :<span class="operator">=</span> expr [, <span class="variable">@var_name</span> :<span class="operator">=</span> expr] ... ;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 自定义变量 冒号可加可不加,建议表示赋值的时候加</span></span><br><span class="line"><span class="keyword">set</span> <span class="variable">@myname</span> <span class="operator">=</span> <span class="string">&#x27;Lloyd&#x27;</span>;</span><br><span class="line"><span class="keyword">set</span> <span class="variable">@myage</span> :<span class="operator">=</span> <span class="number">18</span>;</span><br></pre></td></tr></table></figure><p>语法2</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="variable">@var_name</span> :<span class="operator">=</span> expr [, <span class="variable">@var_name</span> :<span class="operator">=</span> expr] ... ;</span><br><span class="line"><span class="keyword">SELECT</span> 字段名 <span class="keyword">INTO</span> <span class="variable">@var_name</span> <span class="keyword">FROM</span> 表名;</span><br></pre></td></tr></table></figure><ol start="2"><li>使用自定义变量</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 使用</span></span><br><span class="line"><span class="keyword">select</span> <span class="variable">@myname</span>,<span class="variable">@myage</span>;</span><br><span class="line"><span class="comment">-- 将查询的结果赋值给某变量</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">into</span> <span class="variable">@mycount</span> <span class="keyword">from</span> tb_user;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/gVpwnvRb6MTjm4Y.png" alt="007_变量_02.png"></p><blockquote><p>注意: 用户定义的变量无需对其进行声明或初始化，只不过获取到的值为NULL。</p></blockquote><h3 id="局部变量">局部变量</h3><p>局部变量：是根据需要定义的在局部生效的变量，访问之前，需要DECLARE声明。可用作存储过程内的局部变量和输入参数，<strong>局部变量的范围是在其内声明的BEGIN … END块</strong>。</p><ol><li>声明</li></ol><p>语法：<code>DECLARE 变量名 变量类型 [DEFAULT ... ] ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 声明 使用关键字declare 一旦超出范围无法使用</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p2()</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> stu_count <span class="type">int</span> <span class="keyword">default</span> <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">select</span> <span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">into</span> stu_count <span class="keyword">from</span> student;</span><br><span class="line">    <span class="keyword">select</span> stu_count;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">call</span> p2();</span><br></pre></td></tr></table></figure><ol start="2"><li>赋值</li></ol><p>语法：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SET</span> 变量名 <span class="operator">=</span> 值 ;</span><br><span class="line"><span class="keyword">SET</span> 变量名 :<span class="operator">=</span> 值 ;</span><br><span class="line"><span class="keyword">SELECT</span> 字段名 <span class="keyword">INTO</span> 变量名 <span class="keyword">FROM</span> 表名 ... ;</span><br></pre></td></tr></table></figure><h3 id="常使用的“关键字”">常使用的“关键字”</h3><h4 id="if">if</h4><p>和编程语言一样。</p><p>语法</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">IF 条件<span class="number">1</span> <span class="keyword">THEN</span></span><br><span class="line">.....</span><br><span class="line">ELSEIF 条件<span class="number">2</span> <span class="keyword">THEN</span> <span class="comment">-- 可选</span></span><br><span class="line">.....</span><br><span class="line"><span class="keyword">ELSE</span> <span class="comment">-- 可选</span></span><br><span class="line">.....</span><br><span class="line"><span class="keyword">END</span> IF;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p3()</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> score <span class="type">int</span> <span class="keyword">default</span> <span class="number">57</span>;</span><br><span class="line">    <span class="keyword">declare</span> <span class="keyword">result</span> <span class="type">varchar</span>(<span class="number">10</span>);</span><br><span class="line">    if score <span class="operator">&gt;=</span> <span class="number">85</span> <span class="keyword">then</span></span><br><span class="line">        <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;优秀&#x27;</span>;</span><br><span class="line">    elseif score <span class="operator">&gt;=</span> <span class="number">60</span> <span class="keyword">then</span></span><br><span class="line">        <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;及格&#x27;</span>;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;不及格&#x27;</span>;</span><br><span class="line">    <span class="keyword">end</span> if;</span><br><span class="line">    <span class="keyword">select</span> <span class="keyword">result</span>;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">call</span> p3();</span><br></pre></td></tr></table></figure><h4 id="参数">参数</h4><p>类型如下</p><table><thead><tr><th>类型</th><th>含义</th><th>备注</th></tr></thead><tbody><tr><td>IN</td><td>该类参数作为输入，也就是需要调用时传入值</td><td>默认</td></tr><tr><td>OUT</td><td>该类参数作为输出，也就是该参数可以作为返回值</td><td></td></tr><tr><td>INOUT</td><td>既可以作为输入参数，也可以作为输出参数</td><td></td></tr></tbody></table><p>语法</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">PROCEDURE</span> 存储过程名称 ([ <span class="keyword">IN</span><span class="operator">/</span><span class="keyword">OUT</span><span class="operator">/</span><span class="keyword">INOUT</span> 参数名 参数类型 ])</span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"><span class="comment">-- SQL语句</span></span><br><span class="line"><span class="keyword">END</span> ;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 存储过程的参数</span></span><br><span class="line"><span class="comment">-- 输入的参数是score 输出的参数是result</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p4(<span class="keyword">in</span> score <span class="type">int</span>,<span class="keyword">out</span> <span class="keyword">result</span> <span class="type">varchar</span>(<span class="number">10</span>))</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    if score <span class="operator">&gt;=</span> <span class="number">85</span> <span class="keyword">then</span></span><br><span class="line">        <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;优秀&#x27;</span>;</span><br><span class="line">    elseif score <span class="operator">&gt;=</span> <span class="number">60</span> <span class="keyword">then</span></span><br><span class="line">        <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;及格&#x27;</span>;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">        <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;不及格&#x27;</span>;</span><br><span class="line">    <span class="keyword">end</span> if;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"><span class="comment">-- 定义用户变量 @result来接收返回的数据, 用户变量可以不用声明</span></span><br><span class="line"><span class="keyword">call</span> p4(<span class="number">68</span>,<span class="variable">@result</span>);</span><br><span class="line"><span class="keyword">select</span> <span class="variable">@result</span>;<span class="comment">-- 返回结果为及格</span></span><br></pre></td></tr></table></figure><h4 id="case">case</h4><p>和C语言的case基本一样</p><p>语法1</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 含义： 当case_value的值为 when_value1时，执行statement_list1，当值为 when_value2时，</span></span><br><span class="line">执行statement_list2， 否则就执行 statement_list</span><br><span class="line"><span class="keyword">CASE</span> case_value</span><br><span class="line"><span class="keyword">WHEN</span> when_value1 <span class="keyword">THEN</span> statement_list1</span><br><span class="line">[ <span class="keyword">WHEN</span> when_value2 <span class="keyword">THEN</span> statement_list2] ...</span><br><span class="line">[ <span class="keyword">ELSE</span> statement_list ]</span><br><span class="line"><span class="keyword">END</span> <span class="keyword">CASE</span>;</span><br></pre></td></tr></table></figure><p>语法2</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 含义： 当条件search_condition1成立时，执行statement_list1，当条件search_condition2成</span></span><br><span class="line">立时，执行statement_list2， 否则就执行 statement_list</span><br><span class="line"><span class="keyword">CASE</span></span><br><span class="line"><span class="keyword">WHEN</span> search_condition1 <span class="keyword">THEN</span> statement_list1</span><br><span class="line">[<span class="keyword">WHEN</span> search_condition2 <span class="keyword">THEN</span> statement_list2] ...</span><br><span class="line">[<span class="keyword">ELSE</span> statement_list]</span><br><span class="line"><span class="keyword">END</span> <span class="keyword">CASE</span>;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- case</span></span><br><span class="line"><span class="comment">-- 案例：按照季度展示数据</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p6(<span class="keyword">in</span> <span class="keyword">month</span> <span class="type">int</span>)</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> <span class="keyword">result</span> <span class="type">varchar</span>(<span class="number">10</span>);</span><br><span class="line">    <span class="keyword">case</span></span><br><span class="line">        <span class="keyword">when</span> <span class="keyword">month</span> <span class="operator">&gt;=</span> <span class="number">1</span> <span class="keyword">and</span> <span class="keyword">month</span> <span class="operator">&lt;=</span><span class="number">3</span> <span class="keyword">then</span></span><br><span class="line">            <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;第一季度&#x27;</span>;</span><br><span class="line">        <span class="keyword">when</span> <span class="keyword">month</span> <span class="operator">&gt;=</span> <span class="number">4</span> <span class="keyword">and</span> <span class="keyword">month</span> <span class="operator">&lt;=</span><span class="number">6</span> <span class="keyword">then</span></span><br><span class="line">            <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;第二季度&#x27;</span>;</span><br><span class="line">        <span class="keyword">when</span> <span class="keyword">month</span> <span class="operator">&gt;=</span> <span class="number">7</span> <span class="keyword">and</span> <span class="keyword">month</span> <span class="operator">&lt;=</span><span class="number">9</span> <span class="keyword">then</span></span><br><span class="line">            <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;第三季度&#x27;</span>;</span><br><span class="line">        <span class="keyword">when</span> <span class="keyword">month</span> <span class="operator">&gt;=</span> <span class="number">10</span> <span class="keyword">and</span> <span class="keyword">month</span> <span class="operator">&lt;=</span><span class="number">12</span> <span class="keyword">then</span></span><br><span class="line">            <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;第四季度&#x27;</span>;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="keyword">set</span> <span class="keyword">result</span> :<span class="operator">=</span> <span class="string">&#x27;非法参数&#x27;</span>;</span><br><span class="line">    <span class="keyword">end</span> <span class="keyword">case</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">select</span> concat(<span class="string">&#x27;您输入的月份为: &#x27;</span>,<span class="keyword">month</span>,<span class="string">&#x27;,所属的季度为: &#x27;</span>,<span class="keyword">result</span>);</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">call</span> p6(<span class="number">4</span>);</span><br></pre></td></tr></table></figure><h4 id="while">while</h4><p>while 循环是有条件的循环控制语句。满足条件后，再执行循环体中的SQL语句。具体语法为：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 先判定条件，如果条件为true，则执行逻辑，否则，不执行逻辑</span></span><br><span class="line">WHILE 条件 DO</span><br><span class="line"><span class="keyword">SQL</span>逻辑...</span><br><span class="line"><span class="keyword">END</span> WHILE;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- while</span></span><br><span class="line"><span class="comment">-- A. 定义局部变量, 记录累加之后的值;</span></span><br><span class="line"><span class="comment">-- B. 每循环一次, 就会对n进行减1 , 如果n减到0, 则退出循环</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p7(<span class="keyword">in</span> n <span class="type">int</span>)</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> total <span class="type">int</span> <span class="keyword">default</span> <span class="number">0</span>;</span><br><span class="line">    while n <span class="operator">&gt;</span> <span class="number">0</span> do</span><br><span class="line">        <span class="keyword">set</span> total :<span class="operator">=</span> total <span class="operator">+</span> n;</span><br><span class="line">        <span class="keyword">set</span> n:<span class="operator">=</span> n<span class="number">-1</span>;</span><br><span class="line">    <span class="keyword">end</span> while;</span><br><span class="line">    <span class="keyword">select</span> total;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"><span class="comment">-- 从1到10累加循环</span></span><br><span class="line"><span class="keyword">call</span> p7(<span class="number">10</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/IbVMag5PJ794F6l.png" alt="008_循环_01.png"></p><h4 id="repeat">repeat</h4><p>repeat是有条件的循环控制语句, 当满足until声明的条件的时候，则退出循环 。和<code>do ...while </code>很像。具体语法为：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 先执行一次逻辑，然后判定UNTIL条件是否满足，如果满足，则退出。如果不满足，则继续下一次循环</span></span><br><span class="line">REPEAT</span><br><span class="line"><span class="keyword">SQL</span>逻辑...</span><br><span class="line">UNTIL 条件</span><br><span class="line"><span class="keyword">END</span> REPEAT;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- repeat</span></span><br><span class="line"><span class="comment">-- A. 定义局部变量, 记录累加之后的值;</span></span><br><span class="line"><span class="comment">-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p8(<span class="keyword">in</span> n <span class="type">int</span>)</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> total <span class="type">int</span> <span class="keyword">default</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    repeat</span><br><span class="line">        <span class="keyword">set</span> total :<span class="operator">=</span> total <span class="operator">+</span> n;</span><br><span class="line">        <span class="keyword">set</span> n :<span class="operator">=</span> n<span class="number">-1</span>;</span><br><span class="line">    until n<span class="operator">&lt;=</span><span class="number">0</span></span><br><span class="line">    <span class="keyword">end</span> repeat ;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">select</span> total;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">call</span> p8(<span class="number">10</span>);<span class="comment">-- 结果同图008_循环_01 为55</span></span><br></pre></td></tr></table></figure><h4 id="loop">loop</h4><p>LOOP 实现简单的循环，如果不在SQL逻辑中增加退出循环的条件，可以用其来实现简单的死循环。</p><p>语法</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[begin_label:] LOOP</span><br><span class="line">SQL逻辑...</span><br><span class="line">END LOOP [end_label];</span><br><span class="line">-- </span><br><span class="line">-- 以上所有的label都是自定义的标记</span><br><span class="line">LEAVE label; -- 退出指定标记的循环体 相当于break</span><br><span class="line">ITERATE label; -- 直接进入下一次循环 相当于continue</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- loop</span></span><br><span class="line"><span class="comment">-- A. 定义局部变量, 记录累加之后的值;</span></span><br><span class="line"><span class="comment">-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----&gt; leave xx</span></span><br><span class="line"><span class="comment">-- C. 如果当次累加的数据是奇数, 则直接进入下一次循环. --------&gt; iterate xx</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p9(<span class="keyword">in</span> n <span class="type">int</span>)</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> total <span class="type">int</span> <span class="keyword">default</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    sum:loop</span><br><span class="line">        if n<span class="operator">&lt;=</span><span class="number">0</span> <span class="keyword">then</span>  <span class="comment">-- 终止条件</span></span><br><span class="line">            leave sum;</span><br><span class="line">        <span class="keyword">end</span> if;</span><br><span class="line"></span><br><span class="line">        <span class="comment">-- 判断是否为奇数</span></span><br><span class="line">        if n<span class="operator">%</span><span class="number">2</span> <span class="operator">=</span> <span class="number">1</span> <span class="keyword">then</span></span><br><span class="line">            <span class="keyword">set</span> n :<span class="operator">=</span> n<span class="number">-1</span>;</span><br><span class="line">            iterate sum;<span class="comment">-- iterate 表示进入下一次循环，相当于continue</span></span><br><span class="line">        <span class="keyword">end</span> if;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">set</span> total :<span class="operator">=</span> total <span class="operator">+</span> n;</span><br><span class="line">        <span class="keyword">set</span> n :<span class="operator">=</span> n<span class="number">-1</span>;</span><br><span class="line">    <span class="keyword">end</span> loop sum;</span><br><span class="line">    <span class="keyword">select</span> total;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 累加偶数</span></span><br><span class="line"><span class="keyword">call</span> p9(<span class="number">10</span>); <span class="comment">-- 结果为 30</span></span><br></pre></td></tr></table></figure><h3 id="游标">游标</h3><p>游标（CURSOR）是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE，其语法为</p><ol><li>声明游标</li></ol><p>语法：<code>DECLARE 游标名称 CURSOR FOR 查询语句 ;  </code></p><ol start="2"><li>打开游标</li></ol><p>语法：<code>OPEN 游标名称;</code></p><ol start="3"><li>获取游标记录</li></ol><p>语法：<code>FETCH 游标名称 INTO 变量 [, 变量 ] ;  </code></p><ol start="4"><li>关闭游标</li></ol><p>语法：<code>CLOSE 游标名称;</code></p><p>以上语句在不使用条件处理程序的时候虽然能实现需求，但是MySQL会报错，在逻辑上是有漏洞的，需要增加条件处理程序进行修补。</p><p><strong>条件处理程序</strong></p><p>条件处理程序（Handler）可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤(相当于<code>try.. default</code>)</p><p>语法为</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">DECLARE</span> handler_action HANDLER <span class="keyword">FOR</span> condition_value [, condition_value] ... statement ;</span><br><span class="line">handler_action 的取值：</span><br><span class="line">CONTINUE: 继续执行当前程序</span><br><span class="line">EXIT: 终止执行当前程序</span><br><span class="line">condition_value 的取值：</span><br><span class="line"><span class="keyword">SQLSTATE</span> sqlstate_value: 状态码，如 <span class="number">02000</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">SQLWARNING</span>: 所有以<span class="number">01</span>开头的<span class="keyword">SQLSTATE</span>代码的简写</span><br><span class="line"><span class="keyword">NOT</span> FOUND: 所有以<span class="number">02</span>开头的<span class="keyword">SQLSTATE</span>代码的简写</span><br><span class="line"><span class="keyword">SQLEXCEPTION</span>: 所有没有被<span class="keyword">SQLWARNING</span> 或 <span class="keyword">NOT</span> FOUND捕获的<span class="keyword">SQLSTATE</span>代码的简写</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 储存查询结果集的数据类型</span></span><br><span class="line"><span class="comment">-- 声明游标</span></span><br><span class="line"><span class="comment">-- 添加条件处理程序</span></span><br><span class="line"><span class="comment">-- 逻辑:</span></span><br><span class="line"><span class="comment">-- A. 声明游标, 存储查询结果集</span></span><br><span class="line"><span class="comment">-- B. 准备: 创建表结构</span></span><br><span class="line"><span class="comment">-- C. 开启游标</span></span><br><span class="line"><span class="comment">-- D. 获取游标中的记录</span></span><br><span class="line"><span class="comment">-- E. 插入数据到新表中</span></span><br><span class="line"><span class="comment">-- F. 关闭游标</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">procedure</span> p10(<span class="keyword">in</span> uage <span class="type">int</span>)</span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="comment">-- 声明一个游标并记录查询结果的表</span></span><br><span class="line">    <span class="keyword">declare</span> uname <span class="type">varchar</span>(<span class="number">100</span>);</span><br><span class="line">    <span class="keyword">declare</span> upro <span class="type">varchar</span>(<span class="number">100</span>);</span><br><span class="line">    <span class="keyword">declare</span> u_cursor <span class="keyword">cursor</span> <span class="keyword">for</span> <span class="keyword">select</span> name,profession <span class="keyword">from</span> tb_user <span class="keyword">where</span> age <span class="operator">&lt;=</span> uage;</span><br><span class="line">    <span class="comment">-- 当状态码为02000时 将游标关闭</span></span><br><span class="line">    <span class="keyword">declare</span> exit handler <span class="keyword">for</span> <span class="keyword">SQLSTATE</span> <span class="string">&#x27;02000&#x27;</span> <span class="keyword">close</span> u_cursor;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">drop</span> <span class="keyword">table</span> if <span class="keyword">exists</span> tb_user_pro;</span><br><span class="line">    <span class="keyword">create table</span> if <span class="keyword">not</span> <span class="keyword">exists</span>  tb_user_pro(</span><br><span class="line">        id <span class="type">int</span> <span class="keyword">primary key</span> auto_increment,</span><br><span class="line">        name <span class="type">varchar</span>(<span class="number">100</span>),</span><br><span class="line">        profession <span class="type">varchar</span>(<span class="number">100</span>)</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- 开启游标</span></span><br><span class="line">    <span class="keyword">open</span> u_cursor;</span><br><span class="line">    <span class="comment">-- 循环获取表中的记录</span></span><br><span class="line">    while <span class="literal">true</span> do</span><br><span class="line">        <span class="comment">-- 获取游标中的记录并复制给相应的变量</span></span><br><span class="line">        <span class="keyword">fetch</span> u_cursor <span class="keyword">into</span> uname,upro;</span><br><span class="line">        <span class="comment">-- 插入到表中</span></span><br><span class="line">        <span class="keyword">insert into</span> tb_user_pro <span class="keyword">values</span>(<span class="keyword">null</span>,uname,upro);</span><br><span class="line">    <span class="keyword">end</span> while;</span><br><span class="line">    <span class="comment">-- 关闭游标</span></span><br><span class="line">    <span class="keyword">close</span> u_cursor;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"><span class="comment">-- 查询年龄小于40的用户并将其插入表中</span></span><br><span class="line"><span class="keyword">call</span> p10(<span class="number">40</span>);</span><br></pre></td></tr></table></figure><p>错误状态码<a href="https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html">参考网站</a></p><h2 id="存储函数">存储函数</h2><p>存储函数是有返回值的存储过程，存储函数的参数只能是IN类型的。具体语法为</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">FUNCTION</span> 存储函数名称 ([ 参数列表 ])</span><br><span class="line"><span class="keyword">RETURNS</span> type [characteristic ...]</span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line"><span class="comment">-- SQL语句</span></span><br><span class="line"><span class="keyword">RETURN</span> ...;</span><br><span class="line"><span class="keyword">END</span> ;</span><br><span class="line"><span class="comment">-- characteristic说明</span></span><br><span class="line"><span class="comment">-- DETERMINISTIC：相同的输入参数总是产生相同的结果</span></span><br><span class="line"><span class="comment">-- NO SQL ：不包含 SQL 语句</span></span><br><span class="line"><span class="comment">-- READS SQL DATA：包含读取数据的语句，但不包含写入数据的语句</span></span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 存储函数</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">function</span> fun1(n <span class="type">int</span>) <span class="comment">-- 不写默认为in</span></span><br><span class="line"><span class="keyword">returns</span> <span class="type">int</span> <span class="keyword">deterministic</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">declare</span> total <span class="type">int</span> <span class="keyword">default</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    while n <span class="operator">&gt;</span> <span class="number">0</span> do</span><br><span class="line">        <span class="keyword">set</span> total :<span class="operator">=</span> total <span class="operator">+</span> n;</span><br><span class="line">        <span class="keyword">set</span> n :<span class="operator">=</span> n <span class="number">-1</span> ;</span><br><span class="line">    <span class="keyword">end</span> while;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> total;</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"><span class="comment">-- 如果报错就登录Linux的mysql，然后输入set global log_bin_trust_function_creators = 1;即可</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 调用函数</span></span><br><span class="line"><span class="keyword">select</span> fun1(<span class="number">50</span>);</span><br></pre></td></tr></table></figure><p>在mysql8.0版本中binlog默认是开启的，一旦开启了，mysql就要求在定义存储过程时，需要指定characteristic特性，否则就会报错</p><h1>触发器</h1><p>触发器是与表有关的数据库对象，指在insert/update/delete之前(BEFORE)或之后(AFTER)，触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性, 日志记录 , 数据校验等操作 。<br>使用别名OLD和NEW来引用触发器中发生变化的记录内容，这与其他的数据库是相似的。现在触发器还只支持行级触发，不支持语句级触发。</p><p>类型</p><table><thead><tr><th>触发器类型</th><th>NEW 和 OLD</th></tr></thead><tbody><tr><td>INSERT 型触发器</td><td>NEW 表示将要或者已经新增的数据</td></tr><tr><td>UPDATE 型触发器</td><td>OLD 表示修改之前的数据 , NEW 表示将要或已经修改后的数据</td></tr><tr><td>DELETE 型触发器</td><td>OLD 表示将要或者已经删除的数据</td></tr></tbody></table><ol><li>创建</li></ol><p>语法：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TRIGGER</span> trigger_name</span><br><span class="line">BEFORE<span class="operator">/</span>AFTER <span class="keyword">INSERT</span><span class="operator">/</span><span class="keyword">UPDATE</span><span class="operator">/</span><span class="keyword">DELETE</span></span><br><span class="line"><span class="keyword">ON</span> tbl_name <span class="keyword">FOR</span> <span class="keyword">EACH</span> <span class="type">ROW</span> <span class="comment">-- 行级触发器</span></span><br><span class="line"><span class="keyword">BEGIN</span></span><br><span class="line">trigger_stmt ;</span><br><span class="line"><span class="keyword">END</span>;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 建表时创建触发器</span></span><br><span class="line"><span class="keyword">create table</span> user_logs(</span><br><span class="line">                          id <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">not null</span> auto_increment,</span><br><span class="line">                          operation <span class="type">varchar</span>(<span class="number">20</span>) <span class="keyword">not null</span> comment <span class="string">&#x27;操作类型, insert/update/delete&#x27;</span>,</span><br><span class="line">                          operate_time datetime <span class="keyword">not null</span> comment <span class="string">&#x27;操作时间&#x27;</span>,</span><br><span class="line">                          operate_id <span class="type">int</span>(<span class="number">11</span>) <span class="keyword">not null</span> comment <span class="string">&#x27;操作的ID&#x27;</span>,</span><br><span class="line">                          operate_params <span class="type">varchar</span>(<span class="number">500</span>) comment <span class="string">&#x27;操作参数&#x27;</span>,</span><br><span class="line">                          <span class="keyword">primary key</span>(`id`)</span><br><span class="line">)engine<span class="operator">=</span>innodb <span class="keyword">default</span> charset<span class="operator">=</span>utf8;</span><br><span class="line"><span class="comment">-- 插入时创建触发器</span></span><br><span class="line"><span class="comment">-- 插入时的触发器</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">trigger</span> tb_user_insert_trigger</span><br><span class="line">    after <span class="keyword">insert</span> <span class="keyword">on</span> tb_user <span class="keyword">for</span> <span class="keyword">each</span> <span class="type">row</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">insert into</span> user_logs(id,operation,operate_time,operate_id,operate_params) <span class="keyword">values</span></span><br><span class="line">        (<span class="keyword">null</span>,<span class="string">&#x27;insert&#x27;</span>,now(),NEW.id,concat(<span class="string">&#x27;插入的数据内容为:id=&#x27;</span>,NEW.id,<span class="string">&#x27;,name=&#x27;</span>,NEW.name,<span class="string">&#x27;,phone = &#x27;</span>,NEW.phone,<span class="string">&#x27;,email=&#x27;</span>, NEW.email,<span class="string">&#x27;,profession=&#x27;</span>,NEW.profession));</span><br><span class="line"><span class="keyword">end</span>;</span><br></pre></td></tr></table></figure><ol start="2"><li>查看</li></ol><p>语法：<code>SHOW TRIGGERS;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看触发器</span></span><br><span class="line"><span class="keyword">show</span> triggers ;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/xRLljMB1zPG9XHw.png" alt="009_触发器_01.png"></p><ol start="3"><li>删除</li></ol><p>语法：<code>DROP TRIGGER [schema_name.]trigger_name ; -- 如果没有指定 schema_name，默认为当前数据库;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除触发器</span></span><br><span class="line"><span class="keyword">drop</span> <span class="keyword">trigger</span> tb_user_insert_trigger;</span><br></pre></td></tr></table></figure><p>示例，测试触发器是否在插入的时候正常出发</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 测试-插入数据</span></span><br><span class="line"><span class="keyword">insert into</span> tb_user(id, name, phone, email, profession, age, gender, status, createtime)</span><br><span class="line"><span class="keyword">VALUES</span> (<span class="number">25</span>,<span class="string">&#x27;二皇子&#x27;</span>,<span class="string">&#x27;18809091212&#x27;</span>,<span class="string">&#x27;erhuangzi@163.com&#x27;</span>,<span class="string">&#x27;软件工程&#x27;</span>,<span class="number">23</span>,<span class="string">&#x27;1&#x27;</span>,<span class="string">&#x27;1&#x27;</span>,now());</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 测试-更新数据</span></span><br><span class="line"><span class="comment">-- 修改数据的触发器</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">trigger</span> tb_user_update_trigger</span><br><span class="line">    after <span class="keyword">update</span> <span class="keyword">on</span> tb_user <span class="keyword">for</span> <span class="keyword">each</span> <span class="type">row</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">insert into</span> user_logs(id,operation,operate_time,operate_id,operate_params) <span class="keyword">values</span></span><br><span class="line">        (<span class="keyword">null</span>,<span class="string">&#x27;update&#x27;</span>,now(),NEW.id,concat(<span class="string">&#x27;更新前的数据内容为:id=&#x27;</span>,OLD.id,<span class="string">&#x27;,name=&#x27;</span>,OLD.name,<span class="string">&#x27;,phone = &#x27;</span>,OLD.phone,<span class="string">&#x27;,email=&#x27;</span>, OLD.email,<span class="string">&#x27;,profession=&#x27;</span>,OLD.profession,<span class="string">&#x27;</span></span><br><span class="line"><span class="string">           | 更新后的数据内容为:id=&#x27;</span>,NEW.id,<span class="string">&#x27;,name=&#x27;</span>,NEW.name,<span class="string">&#x27;,phone = &#x27;</span>,NEW.phone,<span class="string">&#x27;,email=&#x27;</span>, NEW.email,<span class="string">&#x27;,profession=&#x27;</span>,NEW.profession));</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">update</span> tb_user <span class="keyword">set</span> age <span class="operator">=</span> <span class="number">20</span> <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">23</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 测试-删除数据</span></span><br><span class="line"><span class="comment">-- 删除数据触发器</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">trigger</span> tb_user_delete_trigger</span><br><span class="line">    after <span class="keyword">delete</span> <span class="keyword">on</span> tb_user <span class="keyword">for</span> <span class="keyword">each</span> <span class="type">row</span></span><br><span class="line"><span class="keyword">begin</span></span><br><span class="line">    <span class="keyword">insert into</span> user_logs(id,operation,operate_time,operate_id,operate_params) <span class="keyword">values</span></span><br><span class="line">        (<span class="keyword">null</span>,<span class="string">&#x27;delete&#x27;</span>,now(),OLD.id,concat(<span class="string">&#x27;删除前的数据内容为:id=&#x27;</span>,OLD.id,<span class="string">&#x27;,name=&#x27;</span>,OLD.name,<span class="string">&#x27;,phone = &#x27;</span>,OLD.phone,<span class="string">&#x27;,email=&#x27;</span>, OLD.email,<span class="string">&#x27;,profession=&#x27;</span>,OLD.profession));</span><br><span class="line"><span class="keyword">end</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span> <span class="keyword">from</span> tb_user <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">25</span>;</span><br></pre></td></tr></table></figure><p>插入后</p><p><img src="https://s2.loli.net/2024/11/26/XRCnGSgbQp4uZ5q.png" alt="009_触发器_02.png"></p><p>更新后</p><p><img src="https://s2.loli.net/2024/11/26/YJxd7BpvKR5WuoF.png" alt="009_触发器_03.png"></p><p>删除后</p><p><img src="https://s2.loli.net/2024/11/26/eafiS1lWk9B5g3h.png" alt="009_触发器_04.png"></p><h1>锁</h1><p>定义：锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中，除传统的计算资源（CPU、RAM、I/O）的争用以外，数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题，锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说，锁对数据库而言显得尤其重要，也更加复杂。</p><p>分类为</p><ul><li>全局锁：锁定数据库中的所有表。</li><li>表级锁：每次操作锁住整张表。</li><li>行级锁：每次操作锁住对应的行数据</li></ul><h2 id="全局锁">全局锁</h2><p>全局锁就是对整个数据库实例加锁，加锁后整个实例就处于只读状态，后续的DML的写语句，DDL语句，已经更新操作的事务提交语句都将被阻塞。<br>其典型的使用场景是做<strong>全库的逻辑备份</strong>，对所有的表进行锁定，从而获取一致性视图，保证数据的完整性。</p><p>原理：比如先备份了库存表，在备份订单表之前就被修改了，然后导致备份的订单表和之前备份的库存表对不上。</p><p>解决方案：对数据库进行进行逻辑备份之前，先对<strong>整个数据库加上全局锁</strong>，一旦加了全局锁之后，其他的DDL、DML全部都处于阻塞状态，<strong>但是可以执行DQL语句，也就是处于只读状态</strong>，而数据备份就是查询操作。那么数据在进行逻辑备份的过程中，数据库中的数据就是不会发生变化的，这样就保证了数据的一致性和完整性。</p><ol><li>加全局锁</li></ol><p>语法：<code>flush tables with read lock;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 添加全局锁</span></span><br><span class="line">flush tables <span class="keyword">with</span> read lock ;</span><br></pre></td></tr></table></figure><ol start="2"><li>数据备份</li></ol><p>语法：<code>mysqldump -uroot –p用户密码 指定的表 &gt; 指定名字.sql  ;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 备份(windows系统)</span></span><br><span class="line"><span class="comment">-- mysqldump -h虚拟机的IP -uroot -p你的密码 learning &gt; D:/copy/learning.sql 要保存到的路径</span></span><br></pre></td></tr></table></figure><ol start="3"><li>释放锁</li></ol><p>语法：<code>unlock tables;</code></p><p>加全局锁会有以下问题</p><ul><li>如果在主库上备份，那么在备份期间都不能执行更新，业务基本上就得停摆。</li></ul><p><img src="https://s2.loli.net/2024/11/26/pRtqX7hukbaVD3g.png" alt="010_锁_01.png"></p><p>当解锁之后才能进行更新</p><p><img src="https://s2.loli.net/2024/11/26/vjpDof7VP6QeIkc.png" alt="010_锁_02.png"></p><ul><li>如果在从库上备份，那么在备份期间从库不能执行主库同步过来的二进制日志（binlog），会导致主从延迟。</li></ul><p>在InnoDB引擎中，我们可以在备份时加上参数 --single-transaction 参数来完成不加锁的一致性数据备份。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- InnoDB引擎中，不加锁的一次性备份</span></span><br><span class="line"><span class="comment">-- mysqldump --single-transaction -h虚拟机的IP  -uroot -p你的密码 learning &gt;D:/code/remove/learning.sql</span></span><br></pre></td></tr></table></figure><h2 id="表级锁">表级锁</h2><p>表级锁，每次操作锁住整张表。锁定粒度大，发生锁冲突的概率最高，并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中</p><p>分类</p><ul><li>表锁<ul><li>表共享读锁(read lcok)</li><li>表独占写锁(write lock)</li></ul></li><li>元数据锁(meta data lcok,MDL)</li><li>意向锁</li></ul><h3 id="表锁">表锁</h3><ol><li>添加锁：</li></ol><p>语法：<code>lock tables 表名... read/write;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 添加只读锁</span></span><br><span class="line">lock tables course read;</span><br><span class="line"><span class="comment">-- DQL语句</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> course <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;Java&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/dVLrF6CSuqDoMGj.png" alt="010_锁_03.png"></p><p>在设置共享读锁的时候只能读不能写</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 不能写</span></span><br><span class="line"><span class="keyword">insert into</span> course <span class="keyword">values</span> (<span class="number">5</span>,<span class="string">&#x27;Linux&#x27;</span>);<span class="comment">-- 如果是其他的进程尝试写会阻塞</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/W6PApbLxGRkj5a7.png" alt="010_锁_04.png"></p><ol start="2"><li>释放锁：<code>unlock tables;</code></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 释放表锁</span></span><br><span class="line">unlock tables ;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/jI5PUeVvWTOyl4N.png" alt="010_锁_05.png"></p><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 添加独写锁</span></span><br><span class="line">lock tables course write ;</span><br><span class="line"><span class="comment">-- 可读可写</span></span><br><span class="line"><span class="keyword">insert into</span> course <span class="keyword">values</span> (<span class="number">5</span>,<span class="string">&#x27;Linux&#x27;</span>);<span class="comment">-- 其他的进程尝试读写会阻塞</span></span><br><span class="line"><span class="comment">-- 释放</span></span><br><span class="line">unlock tables ;</span><br></pre></td></tr></table></figure><blockquote><p>读锁不会阻塞其他客户端的读，但是会阻塞写。写锁既会阻塞其他客户端的读，又会阻塞其他客户端的写。</p></blockquote><h3 id="元数据锁">元数据锁</h3><p>meta data lock , 元数据锁，简写<strong>MDL</strong>。MDL加锁过程是系统自动控制，无需显式使用，在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性，在表上有活动<strong>事务</strong>的时候，不可以对元数据进行写入操作。为了避免DML与DDL冲突，保证读写的正确性。<br>这里的<strong>元数据</strong>，大家可以简单理解为就是一张表的<strong>表结构</strong>。 也就是说，某一张表涉及到<strong>未提交的事务时，是不能够修改这张表的表结构的</strong>。<br>在MySQL5.5中引入了MDL，当对一张表进行增删改查的时候，加MDL读锁(共享)；当对表结构进行变更操作的时候，加MDL写锁(排他)。<br>常见的SQL操作时，所添加的元数据锁</p><table><thead><tr><th>对应SQL</th><th>锁类型</th><th>说明</th></tr></thead><tbody><tr><td>lock tables xxx read / write</td><td>SHARED_READ_ONLY / SHARED_NO_READ_WRITE</td><td></td></tr><tr><td>select 、select … lock in share mode</td><td>SHARED_READ</td><td>与SHARED_READ、 SHARED_WRITE兼容，与 EXCLUSIVE互斥</td></tr><tr><td>insert 、update、 delete、select … for update</td><td>SHARED_WRITE</td><td>与SHARED_READ、 SHARED_WRITE兼容，与 EXCLUSIVE互斥</td></tr><tr><td>alter table …</td><td>EXCLUSIVE</td><td>与其他的MDL都互斥</td></tr></tbody></table><p>当执行SELECT、INSERT、UPDATE、DELETE等语句时，添加的是元数据共享锁（SHARED_READ /SHARED_WRITE），之间是兼容的，也就是允许并行开发。</p><p>当执行SELECT语句时，添加的是元数据共享锁（SHARED_READ），会阻塞元数据排他锁（EXCLUSIVE），之间是互斥的。</p><p><img src="https://s2.loli.net/2024/11/26/cJNioFDxT79wL56.png" alt="010_锁_06.png"></p><p>事务提交之后</p><p><img src="https://s2.loli.net/2024/11/26/rFYl18MI6fjVzX3.png" alt="010_锁_07.png"></p><p>查看数据库中的元数据锁</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查看元数据锁</span></span><br><span class="line"><span class="keyword">select</span> object_type,object_schema,object_name,lock_type,lock_duration <span class="keyword">from</span> performance_schema.metadata_locks;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/xsCi6jkAbqpfREv.png" alt="010_锁_08.png"></p><h3 id="意向锁">意向锁</h3><p>为了避免DML在执行时，加的行锁与表锁的冲突，在InnoDB中引入了意向锁，使得表锁不用检查每行数据是否加锁，使用意向锁来减少表锁的检查。</p><p>开启一个事务，然后执行DML操作，在执行DML语句时，会对涉及到的行加行锁。  其他客户端，在对这张表加表锁的时候，会根据该表上所加的意向锁来判定是否可以成功加表锁，而不用逐行判断行锁情况了。</p><p>分类</p><ul><li>意向共享锁(IS): 由语句select … lock in share mode添加 。 与 表锁共享锁(read)兼容，与表锁排他锁(write)互斥。</li><li>意向排他锁(IX): 由insert、update、delete、select…for update添加 。与表锁共享锁(read)及排他锁(write)都互斥，意向锁之间不会互斥。</li></ul><blockquote><p>一旦事务提交了，意向共享锁、意向排他锁，都会自动释放。</p></blockquote><p>查看意向锁及行锁的加锁情况</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> object_schema,object_name,index_name,lock_type,lock_mode,lock_data <span class="keyword">from</span></span><br><span class="line">performance_schema.data_locks;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/PRN87WgcB3inCSY.png" alt="010_锁_09.png"></p><p>注意：意向共享锁与表读锁是兼容的、意向排他锁与表读锁、写锁都是互斥的</p><h2 id="行锁">行锁</h2><p>行级锁，每次操作锁住对应的行数据。锁定粒度最小，发生锁冲突的概率最低，并发度最高。应用在InnoDB存储引擎中。<br>InnoDB的数据是基于索引组织的，行锁是通过对索引上的索引项加锁来实现的，而不是对记录加的<br>锁。对于行级锁，主要分为以下三类：</p><ul><li>行锁（Record Lock）：锁定单个行记录的锁，防止其他事务对此行进行update和delete。在RC、RR隔离级别下都支持。</li></ul><p><img src="https://s2.loli.net/2024/11/27/ghdv8so6mr7CAVY.png" alt="100_演示图_15.png"></p><ul><li>间隙锁（Gap Lock）：锁定索引记录间隙（不含该记录），确保索引记录间隙不变，防止其他事务在这个间隙进行insert，产生幻读。在RR隔离级别下都支持。</li></ul><p><img src="https://s2.loli.net/2024/11/27/B4K8fF5vmpiAxMd.png" alt="100_演示图_16.png"></p><ul><li>临键锁（Next-Key Lock）：行锁和间隙锁组合，同时锁住数据，并锁住数据前面的间隙Gap。在RR隔离级别下支持</li></ul><p><img src="https://s2.loli.net/2024/11/27/FrnjGt8akCq2W5E.png" alt="100_演示图_17.png"></p><p>InnoDB实现了以下两种类型的行锁：</p><ul><li>共享锁（S）：允许一个事务去读一行，阻止其他事务获得相同数据集的排它锁。</li><li>排他锁（X）：允许获取排他锁的事务更新数据，阻止其他事务获得相同数据集的共享锁和排他<br>锁</li></ul><table><thead><tr><th>当前锁类型\请求锁类型</th><th>S(共享锁)</th><th>X(排他锁)</th></tr></thead><tbody><tr><td>S(共享锁)</td><td>兼容</td><td>冲突</td></tr><tr><td>X(排他锁)</td><td>冲突</td><td>冲突</td></tr></tbody></table><p>常见的SQL语句，在执行时，所加的行锁如下：</p><table><thead><tr><th>SQL</th><th>行锁类型</th><th>说明</th></tr></thead><tbody><tr><td>INSERT …</td><td>排他锁</td><td>自动加锁</td></tr><tr><td>UPDATE …</td><td>排他锁</td><td>自动加锁</td></tr><tr><td>DELETE …</td><td>排他锁</td><td>自动加锁</td></tr><tr><td>SELECT（正常）</td><td>不加任何 锁</td><td></td></tr><tr><td>SELECT … LOCK IN SHARE MODE</td><td>共享锁</td><td>需要手动在SELECT之后加LOCK IN SHARE MODE</td></tr><tr><td>SELECT … FOR UPDATE</td><td>排他锁</td><td>需要手动在SELECT之后加FOR UPDATE</td></tr></tbody></table><p>默认情况下，InnoDB在 REPEATABLE READ事务隔离级别运行，InnoDB使用 next-key 锁进行搜索和索引扫描，以防止幻读。</p><ul><li>针对唯一索引进行检索时，对已存在的记录进行等值匹配时，将会自动优化为行锁。</li><li>InnoDB的行锁是针对于索引加的锁，不通过索引条件检索数据，那么InnoDB将对表中的所有记录加锁，此时就会升级为表锁。</li></ul><p>示例</p><p><img src="https://s2.loli.net/2024/11/26/pgS6c4uqOitQlx2.png" alt="010_锁_10.png"></p><p>兼容性</p><p><img src="https://s2.loli.net/2024/11/26/nw8tjYNKgEZ9bpo.png" alt="010_锁_11.png"></p><p><img src="https://s2.loli.net/2024/11/26/a4q61XnvMCwRzge.png" alt="010_锁_12.png"></p><p><img src="https://s2.loli.net/2024/11/26/qDL4jZaR53QVK8c.png" alt="010_锁_13.png"></p><p><img src="https://s2.loli.net/2024/11/26/BPMGV58fFr3gZdO.png" alt="010_锁_14.png"></p><p><img src="https://s2.loli.net/2024/11/26/SQsb3XhgW7HaBOJ.png" alt="010_锁_15.png"></p><p>如果没有索引，更新语句行锁会升级为表锁(因为行锁是对索引项加的锁，而某字段没有索引)  ，这样我们根据索引字段进行更新操作，就可以避免行锁升级为表锁的情况。</p><p>间隙锁和临键锁</p><p>默认情况下，InnoDB在 REPEATABLE READ事务隔离级别运行，InnoDB使用 next-key 锁进行搜<br>索和索引扫描，以防止幻读。</p><ul><li>索引上的等值查询(唯一索引)，给不存在的记录加锁时, 优化为间隙锁 。</li><li>索引上的等值查询(非唯一普通索引)，向右遍历时最后一个值不满足查询需求时，next-keylock 退化为间隙锁。</li><li>索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。</li></ul><blockquote><p>注意：间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存，一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。</p></blockquote><p><img src="https://s2.loli.net/2024/11/26/UZwhtQ5VvrxecpL.png" alt="010_锁_16.png"></p><p>图中方框中的GAP就是间隙锁</p><p>常见的上锁情况</p><ul><li>索引上的等值查询(唯一索引)，给不存在的记录加锁时, 优化为间隙锁</li><li>索引上的等值查询(非唯一普通索引)，向右遍历时最后一个值不满足查询需求时，next-keylock 退化为间隙锁。</li></ul><p>分析</p><p>我们知道InnoDB的B+树索引，叶子节点是有序的双向链表。 假如，我们要根据这个二级索引查询值为18的数据，并加上共享锁，我们是只锁定18这一行就可以了吗？ 并不是，因为是非唯一索引，这个结构中可能有多个18的存在，所以，在加锁时会继续往后找，找到一个不满足条件的值（当前案例中也就是29）。此时会对18加临键锁，并对29之前的间隙加锁。</p><p>索引上的范围查询(唯一索引)–会访问到不满足条件的第一个值为止。  比如查询的条件为id&gt;=19，并添加共享锁。 此时我们可以根据数据库表中现有的数据，将数据分为三个部分：[19]、 (19,25]、 (25,+∞] 所以数据库数据在加锁时，就是将19加了行锁，25的临键锁（包含25及25之前的间隙），正无穷的临键锁(正无穷及之前的间隙)。</p><h1>InnoDB引擎</h1><p>逻辑存储结构见<code>001_存储引擎_06.png</code>和逻辑存储结构部分</p><p>参考黑马和这篇博客<a href="https://blog.csdn.net/2401_83283514/article/details/140721803">InnoDB引擎：底层结构及底层原理</a> ，讲解得足够详细。</p><p>这一部分的重点在于<strong>理解其实现原理</strong>，而不是死记硬背。</p><h1>MySQL管理</h1><p>系统自带的数据库</p><table><thead><tr><th>数据库</th><th>含义</th></tr></thead><tbody><tr><td>mysql</td><td>存储MySQL服务器正常运行所需要的各种信息 （时区、主从、用 户、权限等）</td></tr><tr><td>information_schema</td><td>提供了访问数据库元数据的各种表和视图，包含数据库、表、字段类 型及访问权限等</td></tr><tr><td>performance_schema</td><td>为MySQL服务器运行时状态提供了一个底层监控功能，主要用于收集 数据库服务器性能参数</td></tr><tr><td>sys</td><td>包含了一系列方便 DBA 和开发人员利用 performance_schema 性能数据库进行性能调优和诊断的视图</td></tr></tbody></table><h2 id="常用工具">常用工具</h2><h3 id="mysql的客户端工具"><strong>mysql的客户端工具</strong></h3><p>语法：<code>mysql [options] [database]</code> 在<strong>命令行</strong>中输入</p><p>option</p><ul><li>-u, --user=name #指定用户名</li><li>-p, --password[=name] #指定密码</li><li>-h, --host=name #指定服务器IP或域名</li><li>-P, --port=port #指定连接端口</li><li>-e, --execute=name #执行SQL语句并退出</li></ul><p>-e选项可以在Mysql客户端执行SQL语句，而不用连接到MySQL数据库再执行，对于一些批处理脚本，这种方式尤其方便</p><p><img src="https://s2.loli.net/2024/11/26/cVr7FzLDwqs1lnk.png" alt="012_mysql管理_02.png"></p><h3 id="mysqladmin">mysqladmin</h3><p>是一个执行管理操作的客户端程序。可以用它来检查服务器的配置和当前状态、创建并删除数据库等。</p><p>语法：<code>mysqladmin --help</code></p><p><img src="https://s2.loli.net/2024/11/26/24y6eSqDIjfm8oi.png" alt="012_mysql管理_03.png"></p><p>语法：<code>mysqlamin [options] command </code></p><p>options:</p><ul><li>-u, --user=name #指定用户名</li><li>-p, --password[=name] #指定密码</li><li>-h, --host=name #指定服务器IP或域名</li><li>-P, --port=port #指定连接端口</li></ul><p>示例</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysqladmin -uroot –p1234 drop &#x27;test01&#x27;;</span><br><span class="line">mysqladmin -uroot –p1234 version;</span><br></pre></td></tr></table></figure><h3 id="mysqlbinlog">mysqlbinlog</h3><p>由于服务器生成的二进制日志文件以二进制格式保存，所以如果想要检查这些文本的文本格式，就会使用到mysqlbinlog 日志管理工具。</p><p>语法：<code>mysqlbinlog [options] log-files1 log-files2 ...  </code></p><p>options:</p><ul><li>-d, --database=name 指定数据库名称，只列出指定的数据库相关操作。</li><li>-o, --offset=# 忽略掉日志中的前n行命令。</li><li>-r,–result-file=name 将输出的文本格式日志输出到指定文件。</li><li>-s, --short-form 显示简单格式， 省略掉一些信息。</li><li>–start-datatime=date1 --stop-datetime=date2 指定日期间隔内的所有日志。</li><li>–start-position=pos1 --stop-position=pos2 指定位置间隔内的所有日志。</li></ul><p><img src="https://s2.loli.net/2024/11/26/dHcx7UXhZiTa3kV.png" alt="012_mysql管理_04.png"></p><h3 id="mysqlshow">mysqlshow</h3><p>mysqlshow 客户端对象查找工具，用来很快地查找存在哪些数据库、数据库中的表、表中的列或者索引。</p><p>语法：<code>mysqlshow [options] [db_name [table_name [col_name]]]  </code></p><p>options</p><ul><li>–count 显示数据库及表的统计信息（数据库，表 均可以不指定）</li><li>-i 显示指定数据库或者指定表的状态信息</li></ul><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查询<span class="built_in">test</span>库中每个表中的字段书，及行数</span></span><br><span class="line">mysqlshow -uroot -p2143 test --count</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">查询<span class="built_in">test</span>库中book表的详细情况</span></span><br><span class="line">mysqlshow -uroot -p2143 test book --count</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/cIYJA9Lbjktq3g1.png" alt="012_mysql管理_05.png"></p><h3 id="mysqldump">mysqldump</h3><p>mysqldump 客户端工具用来备份数据库或在不同数据库之间进行数据迁移。备份内容包含创建表，及插入表的SQL语句。</p><p>语法</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">mysqldump [options] db_name [tables]</span><br><span class="line">mysqldump [options] --database/-B db1 [db2 db3...]</span><br><span class="line">mysqldump [options] --all-databases/-A</span><br><span class="line"></span><br><span class="line">连接选项 ：</span><br><span class="line">-u, --user=name 指定用户名</span><br><span class="line">-p, --password[=name] 指定密码</span><br><span class="line">-h, --host=name 指定服务器ip或域名</span><br><span class="line">-P, --port=# 指定连接端口</span><br><span class="line">输出选项：</span><br><span class="line">--add-drop-database 在每个数据库创建语句前加上 drop database 语句</span><br><span class="line">--add-drop-table 在每个表创建语句前加上 drop table 语句 , 默认开启 ; 不开启 (--skip-add-drop-table)</span><br><span class="line">-n, --no-create-db 不包含数据库的创建语句</span><br><span class="line">-t, --no-create-info 不包含数据表的创建语句</span><br><span class="line">-d --no-data 不包含数据</span><br><span class="line">-T, --tab=name 自动生成两个文件：一个.sql文件，创建表结构的语句；一个.txt文件，数据文件</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/k1IKbloOEAeWP2t.png" alt="012_mysql管理_06.png"></p><h3 id="mysqlimport-source">mysqlimport/source</h3><p>mysqlimport 是客户端数据导入工具，用来导入mysqldump 加 -T 参数后导出的文本文件</p><p>语法：<code>mysqlimport [options] db_name textfile1 [textfile2...]  </code></p><p>示例：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysqlimport -uroot -p2143 test /tmp/city.txt</span><br></pre></td></tr></table></figure><p>语法：如果需要导入sql文件,可以使用mysql中的source 指令 :</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source /root/xxxxx.sql  # 这里的/root/xxxxx.sql是文件路径</span><br></pre></td></tr></table></figure><h1>参考</h1><ol><li><a href="https://blog.csdn.net/qq_45938466/article/details/107941557">数据库工作原理</a></li><li>黑马程序员的视频和pdf资料</li><li><a href="https://dev.mysql.com">MySQL官网</a></li></ol>]]></content>
    
    
    <summary type="html">教你学会MySQL的进阶知识，为测试、运维、后端开发、索引优化等方面做准备</summary>
    
    
    
    <category term="MySQL" scheme="https://lloydkai.cn/categories/MySQL/"/>
    
    
    <category term="MySQL" scheme="https://lloydkai.cn/tags/MySQL/"/>
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>数据结构可视化</title>
    <link href="https://lloydkai.cn/posts/ds_visulization/"/>
    <id>https://lloydkai.cn/posts/ds_visulization/</id>
    <published>2024-11-03T12:38:24.000Z</published>
    <updated>2026-04-23T01:44:29.275Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/HzredPNWp2Qs3oJ.jpg" alt></p><blockquote><p>本文主要侧重于可视化的介绍和简单的操作，为后续算法相关的博客提供可视化素材。具体细节请读者自行学习。</p></blockquote><h1>简介</h1><p>数据结构对于计算机系的同学们来说无疑是最基础、最重要的一门课程之一，但是在面对抽象的代码、陌生的概念时感到无从下手，对于数据结构的运行步骤没有一个直观的认识，而数据结构可视化可以帮助同学们用具体的图形理解抽象的算法，从而更好掌握数据结构的精髓。</p><h1>准备工作</h1><h2 id="推荐的可视化网站">推荐的可视化网站</h2><ol><li><a href="https://pythontutor.com/">Python Tutor - Python Online Compiler with Visual AI Help</a></li><li><a href="https://visualgo.net/zh">通过动画可视化数据结构和算法 - VisuAlgo</a> 如果想要动画效果建议使用此网站</li></ol><h2 id="编程基础">编程基础</h2><p>读者至少掌握一门常见的计算机语言(如C++、Python等)的基础语法,否则数据结构可视化无从谈起。</p><h1>可视化开发</h1><h2 id="Python-tutor">Python tutor</h2><p>基础的界面如下，参考图像文字学习</p><p><strong>代码展示和调试区</strong></p><p><img src="https://s2.loli.net/2024/11/26/XstjOaTp1YBQi6L.png" alt="001_可视化开发基础_01"></p><p><strong>调试</strong>：设置断点：点击对应的代码，其颜色会变红，下方会出现红线，如果你点击&lt;prev或者是Next&gt; 会自动跳转到设置有断点的代码行。示例如下</p><p><img src="https://s2.loli.net/2024/11/26/I3YJVByXk86wpFK.png" alt="001_可视化开发基础_03"></p><blockquote><p>注意：执行步数最大为999步</p></blockquote><p><strong>编辑代码区</strong></p><p>编辑完成并确认没有语法错误后点击左下角的<code>visualize execution</code> 将其可视化。</p><p><img src="https://s2.loli.net/2024/11/26/SJsid7fGpbMXEI3.png" alt="001_可视化开发基础_02"></p><p><strong>案例</strong></p><p>可以点击代码区下面的<code>show code examples</code> 感受一下不同例子可视化的效果</p><p><strong>小技巧</strong></p><ol><li>对于Python，可以在编辑代码区可以通过一行<code>#pythontutor_hide: 变量名</code> 将指定的变量在可视化界面中隐藏，读者可以使用此代码隐藏无关变量。对于其他的编译器，可以在可视化执行之后点击<code>Move and hide objects</code> 按照说明将指定的对象隐藏。</li><li>可视化执行之后，可以点击左下方的两个按钮生成链接或者是iframe嵌入到markdown文件格式里面，甚至可以执行\(^o^)/~，如下</li></ol><iframe width="800" height="500" frameborder="0" src="https://pythontutor.com/iframe-embed.html#code=%23include%20%3Ciostream%3E%0A%0Aint%20main%28%29%20%7B%0A%20%20int*%20x%20%3D%20new%20int%5B3%5D%3B%0A%20%20x%5B1%5D%20%3D%2020%3Bint*%20p%20%3D%20%26x%5B1%5D%3B%20//%20pointer%20into%20middle%0A%20%20const%20char**%20fruit%20%3D%20new%20const%20char*%5B3%5D%3B%0A%20%20fruit%5B1%5D%20%3D%20%22bananas%22%3B%0A%20%20std%3A%3Acout%20%3C%3C%20%22Yum%20%22%20%3C%3C%20*p%20%3C%3C%20%22%20%22%20%3C%3C%20fruit%5B1%5D%3B%0A%20%20return%200%3B%0A%7D&codeDivHeight=400&codeDivWidth=350&cumulative=false&curInstr=0&heapPrimitives=nevernest&origin=opt-frontend.js&py=cpp_g%2B%2B9.3.0&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe><p><strong>建议以上网址链接用电脑端打开，手机端会有界面溢出的问题</strong></p><p><img src="https://s2.loli.net/2024/11/26/cWnDdbAMEBvuUjk.png" alt="001_可视化开发基础_04"></p><h2 id="visualgo">visualgo</h2><p>这个网站有中文，同时也有教程，这里就不展开教学了，比较适合需要动画效果的代码展示。</p><h2 id="gif录制">gif录制</h2><p>软件：<a href="https://www.screentogif.com/">ScreenToGif</a> 选择对应的版本下载即可。</p><p>参考教程：链接:<a href="https://www.bilibili.com/video/BV1fb411P74h?vd_source=bb8dacb993f11c0e39f8147c98a2894c">screentogif</a></p><p>示例如下(gif相当于图片，可以直接在markdown文件里面按照图片的格式插入)</p><p><img src="https://s2.loli.net/2024/11/26/eAGhpQafRJqD1PM.gif" alt="动画"></p><h1>参考</h1><ol><li><a href="https://pythontutor.com/">Python Tutor - Python Online Compiler with Visual AI Help</a></li><li><a href="https://visualgo.net/zh">通过动画可视化数据结构和算法 - VisuAlgo</a></li><li><a href="https://www.screentogif.com/">ScreenToGif</a>：软件下载官方网站</li><li><a href="https://www.bilibili.com/video/BV1fb411P74h?vd_source=bb8dacb993f11c0e39f8147c98a2894c">screentogif</a> ：B站教程</li></ol>]]></content>
    
    
    <summary type="html">本文章介绍了一些数据结构可视化开发的网站，帮助读者进行数据结构可视化开发。</summary>
    
    
    
    <category term="data structure" scheme="https://lloydkai.cn/categories/data-structure/"/>
    
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="data structure" scheme="https://lloydkai.cn/tags/data-structure/"/>
    
  </entry>
  
  <entry>
    <title>MySQL学习笔记(一)基础篇</title>
    <link href="https://lloydkai.cn/posts/mysql-series-one/"/>
    <id>https://lloydkai.cn/posts/mysql-series-one/</id>
    <published>2024-10-30T12:23:09.000Z</published>
    <updated>2026-04-23T01:42:05.751Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/06/10/QHqgRXDGwunkt4l.png" alt></p><blockquote><p>注：本篇博客大部分是黑马pdf中的内容，根据我自己学习的实际情况进行修改和补充。</p></blockquote><h1>简介</h1><p>数据库(database 简称DB)是存储数据的仓库，数据是有组织的进行存储.而数据库管理系统(database management system)是操作和管理数据库的大型软件(常用的有oracle、mysql等).SQL是操作关系型数据库的编程语言，定义了一套操作关系型数据库统一标准。</p><h1>准备工作</h1><blockquote><ol><li>建议读者具有一定的Linux基础再来学习本篇博客</li><li>本博客所使用的是Mysql8.0的版本</li><li>所有代码中的注释均使用<code>--</code>或者<code>/**/</code>以便适配不同的sql语言</li></ol></blockquote><h2 id="下载">下载</h2><h3 id="Windows下载MySQL8-0版本">Windows下载MySQL8.0版本</h3><p>官网：<a href="https://dev.mysql.com/downloads/windows/installer/">MySQL :: Download MySQL Installer</a></p><p>如图所示进行下载.<strong>后面一路默认安装</strong>，在输入mysql中root用户密码的时候建议稍复杂一点，牢记即可。<br><img src="https://s2.loli.net/2024/11/26/bdRZNfpYy6avmG3.png" alt="001_mysql安装_01.png"></p><p>然后再配置环境变量：在“开始”中搜索”编辑系统环境变量“-找到PATH点击去，将MySQL server的安装目录下的bin目录添加到环境变量，如图</p><p><img src="https://s2.loli.net/2024/11/26/HUo6qg2Bv1kWY5F.png" alt="001_mysql安装_02.png"></p><h3 id="Linux中下载MySQL8-0版本">Linux中下载MySQL8.0版本</h3><p>同样在上面的官网下载，选择合适的版本(当然用Linux联网下载也是可以的)。如果速度慢可以考虑此链接<a href="https://mirrors.tuna.tsinghua.edu.cn/mysql/">Index of /mysql/ | 清华大学开源软件镜像站</a></p><p><img src="https://s2.loli.net/2024/11/26/iqDna5rpZuIU7Ak.png" alt="001_mysql安装_03.png"></p><ol><li>用Xftp连接到Linux，然后将其上传到根目录下</li><li>创建目录并解压.注意这里的文件名是你自己下的文件的名字。</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir mysql</span><br><span class="line">tar -xvf mysql-8.0.40-1.e17.x86_64.rpm-bundle.tar -C mysql</span><br></pre></td></tr></table></figure><ol start="3"><li>安装MySQL的安装包(注意严格按照顺序执行命令，否则会出现依赖错误)</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">cd mysql</span><br><span class="line"></span><br><span class="line">rpm -ivh mysql-community-common-8.0.40-1.el7.x86_64.rpm </span><br><span class="line"></span><br><span class="line">rpm -ivh mysql-community-client-plugins-8.0.40-1.el7.x86_64.rpm </span><br><span class="line"></span><br><span class="line">rpm -ivh mysql-community-libs-8.0.40-1.el7.x86_64.rpm </span><br><span class="line"></span><br><span class="line">rpm -ivh mysql-community-libs-compat-8.0.40-1.el7.x86_64.rpm</span><br><span class="line"></span><br><span class="line">yum install openssl-devel</span><br><span class="line"></span><br><span class="line">rpm -ivh  mysql-community-devel-8.0.40-1.el7.x86_64.rpm</span><br><span class="line"></span><br><span class="line">rpm -ivh mysql-community-client-8.0.40-1.el7.x86_64.rpm</span><br><span class="line"></span><br><span class="line">rpm -ivh  mysql-community-server-8.0.40-1.el7.x86_64.rpm</span><br></pre></td></tr></table></figure><ol start="4"><li>启动MySQL服务</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl start mysqld</span><br></pre></td></tr></table></figure><p>设置<strong>开机自启动</strong>,以后只要打开Linux就会启动mysql</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl enable mysqld</span><br></pre></td></tr></table></figure><ol start="5"><li>登录MySQL并设置root密码</li></ol><p>查看自动生成的密码：<code>grep 'temporary password' /var/log/mysqld.log</code>并将其复制</p><p>命令行输入<code>mysql -u root -p</code> 并粘贴刚才的密码(<strong>shift+insert</strong>)</p><blockquote><p>注意 以下的命令输入是在登录MySQL后的</p></blockquote><p>登录到MySQL之后，需要将自动生成的不便记忆的密码修改了，修改成自己熟悉的便于记忆的密码。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER  USER  &#x27;root&#x27;@&#x27;localhost&#x27;  IDENTIFIED BY &#x27;1234(你自己设置密码)&#x27;;</span><br></pre></td></tr></table></figure><p>执行上述的SQL会报错，原因是因为设置的密码太简单，密码复杂度不够。我们可以设置密码的复杂度为简单类型(自己学习用可以设置简单密码，但是在<strong>生产中不建议使用简单密码</strong>)。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">set global validate_password.policy = 0;</span><br></pre></td></tr></table></figure><p>降低密码的校验规则之后，再次执行上述修改密码的指令。</p><ol start="6"><li>创建远程登录用户</li></ol><p>默认的root用户只能当前节点localhost访问，是无法远程访问的，我们还需要创建一个root账户，用户远程访问</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">create user &#x27;root&#x27;@&#x27;%&#x27; IDENTIFIED WITH mysql_native_password BY &#x27;自己设置密码&#x27;;</span><br></pre></td></tr></table></figure><p>分配权限</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grant all on *.* to &#x27;root&#x27;@&#x27;%&#x27;;</span><br></pre></td></tr></table></figure><p>后面通过其他软件进行远程登录的时候就可以使用此用户进行登录了。</p><p>示例：使用IDEA进行远程登录</p><p>点击“+”-”数据源“-“MySQL”，然后按照图填写相关配置即可。</p><p><img src="https://s2.loli.net/2024/11/26/VBOFamZifkuNLCy.png" alt="001_mysql安装_04.png"></p><h2 id="Windows启动MySQL">Windows启动MySQL</h2><p>打开方式有如下三种</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">命令行</button><button type="button" class="tab">系统控制</button><button type="button" class="tab">开机自启动</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>通过命令行的方式打开(Windows11)</strong></p><ol><li>按<code>win+r</code>键，在弹出的窗口内输入cmd</li><li>再按ctrl+shift+enter以管理员的方式运行</li><li>输入<code>net start MySQL服务名(例如本机是mysql80)</code></li><li>停止Mysql命令：<code>net stop mMySQL服务名</code></li></ol><p><img src="https://s2.loli.net/2024/11/26/YF6mcAWnj8k1StC.png" alt="001_mysql安装_05.png"></p></div><div class="tab-item-content"><ol><li>按<code>win+r</code>键，在弹出的窗口内输入cmd</li><li>输入services.msc打开服务，找到对应的mysql，右键启动即可</li></ol></div><div class="tab-item-content"><p>按<code>win+x</code>键，选择“任务管理器”，在左侧栏点击“服务”，搜索mysql，然后鼠标右键点击“<strong>打开服务</strong>”(或者按照系统控制的方法打开服务也行)，然后找到mysql右键-“属性”，点开“启动类型”并选择自动，点击应用并确定即可实现开机自启动。</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="MySQL连接方式">MySQL连接方式</h2><table><thead><tr><th>方式</th><th>效果</th><th>难度</th><th>连接操作</th></tr></thead><tbody><tr><td>MySQL 8.0 Command Line Client</td><td>和命令行一样，可视性不是特别强</td><td>低，安装MySQL自带的</td><td>开始界面搜索MySQL 8.0 Command Line Client，然后输入密码即可</td></tr><tr><td><strong>Windows命令行</strong></td><td>命令行，无需多言</td><td>中，需要在系统属性里的PATH里面配置环境变量(就是<code>你的MySQL路径\bin</code>)</td><td>打开命令行之后输入<code>mysql -u用户名 -p密码</code>      或者<code>mysql -u root -p </code>  加密输入密码防止泄露</td></tr></tbody></table><p>Windows命令行打开示意图(<strong>和Linux一样</strong>)</p><p><img src="https://s2.loli.net/2024/11/26/W6Iyz1GEuvxLlFh.png" alt="001_mysql安装_06.png"></p><p>命令行工具指令讲解</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql[-h 127.0.0.1][-P 3306] -u root -p</span><br></pre></td></tr></table></figure><p>其中-h:MySQL服务所在的主机IP；-P:MySOL服务端口号，默认3306；-u:MySQL数据库用户名-p:MySQL数据库用户名对应的密码</p><hr><h1>MySQL基础篇</h1><h2 id="概念解析">概念解析</h2><p><strong>关系型数据库</strong></p><p>概念：建立在关系模型基础上，由多张相互连接的二维表组成的数据库。二维表就是由行和列组成的表，就是Excel中的那种表</p><p><strong>SQL语言</strong></p><blockquote><p>Structured Query Language  操作关系型数据库的编程语言</p></blockquote><p>无论是MySQL，还是oracle等其他的数据库，都遵守一定的SQL通用语法，特点如下</p><ol><li><strong>不区分大小写</strong>，但<u>建议关键字大写</u></li><li>注释：<code>#</code>或者是<code>--</code>单行注释，<code>/**/</code>是多行注释</li><li>可以单行或者多行书写，以分号结尾</li></ol><h2 id="DDL">DDL</h2><blockquote><p>Data Definition Languages  即数据定义语言</p></blockquote><h3 id="数据库操作">数据库操作</h3><blockquote><p>以下我使用图形化工具IDEA展示效果，读者可以使用datagrip、Tomcat等图形化工具进行操作学习</p><p>由于hexo的原因，以下所有代码块中的语言都改为SQL，<strong>除特别指出，以下SQL均代表MySQL</strong></p></blockquote><ol><li>查询所有数据库</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> databases;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/fRWn4by6L1qCPji.png" alt="002_DDL_01.png"></p><p>因为我之间创建过一些数据库，所以会有读者没有的数据库，读者无需在意。</p><ol start="2"><li>查询当前数据库</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> database();</span><br></pre></td></tr></table></figure><ol start="3"><li>创建数据库</li></ol><p>语法：<code>create database [ if not exists ] 数据库名 [ default charset 字符集 ] [ collate 排序规则 ] ;  </code></p><blockquote><p>语法讲解</p><ol><li>[]内的内容表示非必写，或者是限定条件</li><li>对于某些版本的MySQL(比如5.7版本)可能需要设置字符集为utf-8</li></ol></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 由于mysql中不能创建两个名称相同的数据库，可以使用if语句事先判断是否存在同名的数据库</span></span><br><span class="line"><span class="keyword">create</span> database if <span class="keyword">not</span> <span class="keyword">exists</span> test1;</span><br><span class="line"><span class="comment">-- 创建一个数据库并指定字符集</span></span><br><span class="line"><span class="keyword">create</span> database if <span class="keyword">not</span> <span class="keyword">exists</span> Mydatabase01 <span class="keyword">default</span> charset utf8mb4;</span><br></pre></td></tr></table></figure><ol start="4"><li>删除数据库</li></ol><p>语法：<code>drop database [ if exists ] 数据库名 ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">drop</span> database test3;</span><br></pre></td></tr></table></figure><ol start="5"><li>切换数据库</li></ol><p>语法：<code>use 数据库名</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">use test1;</span><br></pre></td></tr></table></figure><h3 id="表操作">表操作</h3><ol><li>展示当前数据库中所有的表</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> tables;</span><br></pre></td></tr></table></figure><ol start="2"><li>查看表结构</li></ol><p>语法：<code>desc 表名</code>.可以查看表的字段、数据类型、主键等</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">desc</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ntjiL7VQqPsYzWf.png" alt="002_DDL_02.png"></p><p>查看表中所有的数据</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">describe</span> test1.emps;</span><br><span class="line"><span class="comment">-- 等效于以下语句</span></span><br><span class="line"><span class="keyword">show</span> columns <span class="keyword">from</span> emps;</span><br></pre></td></tr></table></figure><ol start="3"><li>查询指定表的建表语句</li></ol><p>语法：<code>show create table 表名</code>。就是查看创建表所使用的代码。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">show</span> <span class="keyword">create table</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/mLwBbvJaqi2VzYF.png" alt="002_DDL_03.png"></p><ol start="4"><li>创建表结构</li></ol><p>语法如下：注意[…]为可选函数，最后一个字段后面没有逗号</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE TABLE</span> 表名(</span><br><span class="line">字段<span class="number">1</span> 字段<span class="number">1</span>类型 [COMMENT 字段<span class="number">1</span>注释 ],</span><br><span class="line">字段<span class="number">2</span> 字段<span class="number">2</span>类型 [COMMENT 字段<span class="number">2</span>注释 ],</span><br><span class="line">字段<span class="number">3</span> 字段<span class="number">3</span>类型 [COMMENT 字段<span class="number">3</span>注释 ],</span><br><span class="line">......</span><br><span class="line">字段n 字段n类型 [COMMENT 字段n注释 ]</span><br><span class="line">) [ COMMENT 表注释 ] ;</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">create table</span> tb_user(</span><br><span class="line">    id <span class="type">int</span> comment <span class="string">&#x27;编号&#x27;</span>,</span><br><span class="line">    name <span class="type">varchar</span>(<span class="number">50</span>) comment <span class="string">&#x27;姓名&#x27;</span>,</span><br><span class="line">    age <span class="type">int</span> comment <span class="string">&#x27;年龄&#x27;</span>,</span><br><span class="line">    gender <span class="type">varchar</span>(<span class="number">1</span>) comment <span class="string">&#x27;性别&#x27;</span></span><br><span class="line">) comment <span class="string">&#x27;用户表&#x27;</span>;</span><br></pre></td></tr></table></figure><p>查看错误与警告</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 展示错误与警告</span></span><br><span class="line"><span class="keyword">show</span> errors ;</span><br><span class="line"><span class="keyword">show</span> warnings ;</span><br></pre></td></tr></table></figure><h4 id="数据类型">数据类型</h4><p>常见的数据类型基本上和其他高级编程语言大致相同，主要分为三类，数值类型、字符串类型、日期时间类型。根据字段要存储的数据选择合适的数据类型(比如年龄适合用tinyint unsigned)</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">数值类型</button><button type="button" class="tab">字符串类型</button><button type="button" class="tab">日期类型</button></div><div class="tab-contents"><div class="tab-item-content active"><table><thead><tr><th>类型</th><th>大小</th><th>有符号(SIGNED)范围</th><th>无符号(UNSIGNED)范围</th><th>描述</th></tr></thead><tbody><tr><td>TINYINT</td><td>1byte</td><td>(-128，127)</td><td>(0，255)</td><td>小整 数值</td></tr><tr><td>SMALLINT</td><td>2bytes</td><td>(-32768，32767)</td><td>(0，65535)</td><td>大整 数值</td></tr><tr><td>MEDIUMINT</td><td>3bytes</td><td>(-8388608，8388607)</td><td>(0，16777215)</td><td>大整 数值</td></tr><tr><td>INT/INTEGER</td><td>4bytes</td><td>(-2147483648， 2147483647)</td><td>(0，4294967295)</td><td>大整 数值</td></tr><tr><td>BIGINT</td><td>8bytes</td><td>(-2<sup>63，2</sup>63-1)</td><td>(0，2^64-1)</td><td>极大 整数 值</td></tr><tr><td>FLOAT</td><td>4bytes</td><td>(-3.402823466 E+38， 3.402823466351 E+38)</td><td>0 和 (1.175494351 E- 38，3.402823466 E+38)</td><td>单精 度浮 点数 值</td></tr><tr><td>DOUBLE</td><td>8bytes</td><td>(-1.7976931348623157 E+308， 1.7976931348623157 E+308)</td><td>0 和 (2.2250738585072014 E-308， 1.7976931348623157 E+308)</td><td>双精 度浮 点数 值</td></tr><tr><td>DECIMAL</td><td></td><td>依赖于M(精度)和D(标度)的值(精度就是数字长度，标度就是小数点后几位)</td><td>依赖于M(精度)和D(标度)的值</td><td>小数值(精确确定点数)</td></tr></tbody></table></div><div class="tab-item-content"><table><thead><tr><th>类型</th><th>大小</th><th>描述</th></tr></thead><tbody><tr><td>CHAR</td><td>0-255 bytes</td><td><strong>定长</strong>字符串(需要指定长度)</td></tr><tr><td>VARCHAR</td><td>0-65535 bytes</td><td><strong>变长</strong>字符串(需要指定最大长度)</td></tr><tr><td>TINYBLOB</td><td>0-255 bytes</td><td>不超过255个字符的二进制数据</td></tr><tr><td>TINYTEXT</td><td>0-255 bytes</td><td>短文本字符串</td></tr><tr><td>BLOB</td><td>0-65 535 bytes</td><td>二进制形式的长文本数据</td></tr><tr><td>TEXT</td><td>0-65 535 bytes</td><td>长文本数据</td></tr><tr><td>MEDIUMBLOB</td><td>0-16 777 215 bytes</td><td>二进制形式的中等长度文本数据</td></tr><tr><td>MEDIUMTEXT</td><td>0-16 777 215 bytes</td><td>中等长度文本数据</td></tr><tr><td>LONGBLOB</td><td>0-4 294 967 295 bytes</td><td>二进制形式的极大文本数据</td></tr><tr><td>LONGTEXT</td><td>0-4 294 967 295 bytes</td><td>极大文本数据</td></tr></tbody></table></div><div class="tab-item-content"><table><thead><tr><th>类型</th><th>大 小</th><th>范围</th><th>格式</th><th>描述</th></tr></thead><tbody><tr><td>DATE</td><td>3</td><td>1000-01-01 至 9999-12-31</td><td>YYYY-MM-DD</td><td>日期值</td></tr><tr><td>TIME</td><td>3</td><td>-838:59:59 至 838:59:59</td><td>HH:MM:SS</td><td>时间值或持续 时间</td></tr><tr><td>YEAR</td><td>1</td><td>1901 至 2155</td><td>YYYY</td><td>年份值</td></tr><tr><td>DATETIME</td><td>8</td><td>1000-01-01 00:00:00 至 9999-12-31 23:59:59</td><td>YYYY-MM-DD HH:MM:SS</td><td>混合日期和时 间值</td></tr><tr><td>TIMESTAMP</td><td>4</td><td>1970-01-01 00:00:01 至 2038-01-19 03:14:07</td><td>YYYY-MM-DD HH:MM:SS</td><td>混合日期和时 间值，时间戳</td></tr></tbody></table></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 案例-设置员工表</span></span><br><span class="line"><span class="comment">-- 1.编号（纯数字）</span></span><br><span class="line"><span class="comment">-- 2.员工工号(字符串类型，长度不超过10位)</span></span><br><span class="line"><span class="comment">-- 3.员工姓名(字符串类型，长度不超过10位)</span></span><br><span class="line"><span class="comment">-- 4.性别(男/女，存储一个汉字)</span></span><br><span class="line"><span class="comment">-- 5.年龄(正常人年龄，不可能存储负数)</span></span><br><span class="line"><span class="comment">-- 6.身份证号(二代身份证号均为18位，身份证中有x这样的字符)</span></span><br><span class="line"><span class="comment">-- 7.入职时间（取值年月日即可）</span></span><br><span class="line"><span class="keyword">create table</span> emp(</span><br><span class="line">    id <span class="type">int</span> comment <span class="string">&#x27;编号&#x27;</span>,</span><br><span class="line">    workno <span class="type">varchar</span>(<span class="number">10</span>) comment <span class="string">&#x27;工号&#x27;</span>,</span><br><span class="line">    name <span class="type">varchar</span>(<span class="number">10</span>) comment <span class="string">&#x27;姓名&#x27;</span>,</span><br><span class="line">    gender <span class="type">char</span>(<span class="number">1</span>) comment <span class="string">&#x27;性别&#x27;</span>,</span><br><span class="line">    age tinyint unsigned comment <span class="string">&#x27;年龄&#x27;</span>,</span><br><span class="line">    idcard <span class="type">char</span>(<span class="number">18</span>) comment <span class="string">&#x27;身份证号&#x27;</span>,</span><br><span class="line">    entrydate <span class="type">date</span> comment <span class="string">&#x27;入职时间&#x27;</span></span><br><span class="line">)comment <span class="string">&#x27;员工表&#x27;</span>;</span><br></pre></td></tr></table></figure><h4 id="增删查改">增删查改</h4><ol><li>添加字段</li></ol><p>语法：<code>ALTER TABLE 表名 ADD 字段名 类型 (长度) [ COMMENT 注释 ] [ 约束 ];  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter table</span> emp <span class="keyword">add</span> nickname <span class="type">varchar</span>(<span class="number">20</span>) comment <span class="string">&#x27;昵称&#x27;</span>;</span><br></pre></td></tr></table></figure><ol start="2"><li>修改数据类型</li></ol><p>语法：<code>ALTER TABLE 表名 MODIFY 字段名 新数据类型 (长度);  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter table</span> emp change nickname username <span class="type">varchar</span>(<span class="number">30</span>) comment <span class="string">&#x27;用户名&#x27;</span>;</span><br></pre></td></tr></table></figure><ol start="3"><li>修改字段和字段类型</li></ol><p>语法：<code>ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型 (长度) [ COMMENT 注释 ] [ 约束 ];</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ALTER TABLE</span> emp CHANGE nickname username <span class="type">varchar</span>(<span class="number">30</span>) COMMENT <span class="string">&#x27;昵称&#x27;</span>;</span><br></pre></td></tr></table></figure><ol start="4"><li>删除字段</li></ol><p>语法：<code>ALTER TABLE 表名 DROP 字段名;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter table</span> emp <span class="keyword">drop</span> username;</span><br></pre></td></tr></table></figure><ol start="5"><li>修改表名</li></ol><p>语法：<code>ALTER TABLE 表名 RENAME TO 新表名  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">alter table</span> emp rename <span class="keyword">to</span> employee;</span><br></pre></td></tr></table></figure><ol start="6"><li>删除表</li></ol><p>语法：<code>DROP TABLE [ IF EXISTS ] 表名;  </code>;</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 只有表名存在的时候才会删除该表，不存在的时候就不会删除</span></span><br><span class="line"><span class="keyword">drop</span> <span class="keyword">table</span> if <span class="keyword">exists</span> tb_user;</span><br></pre></td></tr></table></figure><ol start="7"><li>删除并重新创建表</li></ol><p>语法：<code>TRUNCATE TABLE 表名;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除并创建该表,这样就实现了数据清空但保留表结构的效果</span></span><br><span class="line"><span class="keyword">truncate</span> <span class="keyword">table</span> employee;</span><br></pre></td></tr></table></figure><blockquote><p>注意：以上操作虽然可以通过图形化界面工具直接实现，但数据库常常在Linux上操作，建议读者使用命令行的方式实现有关需求。</p><p>方法：右键数据库-“新建”-“查询控制台”，然后就可以在界面中编写sql并执行。</p></blockquote><h2 id="DML">DML</h2><blockquote><p>Data Manipulation Languages  数据操作语言</p></blockquote><p><strong>增删查改数据</strong></p><ol><li>给指定字段添加数据</li></ol><p>语法：<code>INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...);  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 示例</span></span><br><span class="line"><span class="keyword">insert into</span> employee(id, workno, name, gender, age, idcard, entrydate) <span class="keyword">VALUES</span>(<span class="number">1</span>,<span class="string">&#x27;1&#x27;</span>,<span class="string">&#x27;itcast&#x27;</span>,<span class="string">&#x27;男&#x27;</span>,<span class="number">10</span>,<span class="string">&#x27;123456789012345678&#x27;</span>,<span class="string">&#x27;2000-11-01&#x27;</span>);</span><br></pre></td></tr></table></figure><p>数据查询如下</p><p><img src="https://s2.loli.net/2024/11/26/4QnbPRFrs8f1ayD.png" alt="003_DML_01.png"></p><p><u>如果是要给全部字段添加数据，就无需写字段名</u></p><ol start="2"><li>批量添加</li></ol><p>语法：<code>INSERT INTO 表名 (字段名1, 字段名2, ...) VALUES (值1, 值2, ...), (值1, 值2, ...), (值1, 值2, ...) ;  </code>如果是全部字段添加数据则无需写明字段。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">insert into</span> employee <span class="keyword">values</span></span><br><span class="line">(<span class="number">3</span>,<span class="string">&#x27;3&#x27;</span>,<span class="string">&#x27;韦一笑&#x27;</span>,<span class="string">&#x27;男&#x27;</span>,<span class="number">38</span>,<span class="string">&#x27;123456789012345670&#x27;</span>,<span class="string">&#x27;2005-01-01&#x27;</span>),</span><br><span class="line">(<span class="number">4</span>,<span class="string">&#x27;4&#x27;</span>,<span class="string">&#x27;赵敏&#x27;</span>,<span class="string">&#x27;女&#x27;</span>,<span class="number">18</span>,<span class="string">&#x27;123456789012345670&#x27;</span>,<span class="string">&#x27;2005-01-01&#x27;</span>);</span><br></pre></td></tr></table></figure><blockquote><p>注意</p><ol><li>插入数据时指定的字段顺序需要与值的顺序是一一对应的</li><li>字符串和日期类型要在<strong>引号</strong>中</li><li>数据应在规定范围内，否则会报错</li></ol></blockquote><ol start="3"><li>修改数据</li></ol><p>语法：<code>UPDATE 表名 SET 字段名1 = 值1 , 字段名2 = 值2 , .... [ WHERE 条件 ] ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 将id为1的员工的员工名字改为itheima，性别改为女</span></span><br><span class="line"><span class="keyword">update</span> employee <span class="keyword">set</span> name <span class="operator">=</span> <span class="string">&#x27;itheima&#x27;</span>,gender <span class="operator">=</span> <span class="string">&#x27;女&#x27;</span> <span class="keyword">where</span> id <span class="operator">=</span> <span class="number">1</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ZNFgmhJuCG9QEwt.png" alt="003_DML_02.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 将所有员工的入职时期设置为同一个时期</span></span><br><span class="line"><span class="keyword">update</span> employee <span class="keyword">set</span> entrydate  <span class="operator">=</span> <span class="string">&#x27;2003-01-01&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/QUc96FmpXdLD74W.png" alt="003_DML_03.png"></p><blockquote><p>如果修改数据没有where语句，默认修改所有数据</p></blockquote><ol start="4"><li>删除数据</li></ol><p>语法：<code>DELETE FROM 表名 [ WHERE 条件 ]   ;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除所有员工性别为女的数据</span></span><br><span class="line"><span class="keyword">delete</span> <span class="keyword">from</span> employee <span class="keyword">where</span> gender <span class="operator">=</span> <span class="string">&#x27;女&#x27;</span>;</span><br><span class="line"><span class="comment">-- 相当于删除所有数据</span></span><br><span class="line"><span class="keyword">delete</span> <span class="keyword">from</span> employee; </span><br></pre></td></tr></table></figure><blockquote><p>delete语句不能删除某一个字段的值，需要使用update将该字段设置为null</p></blockquote><h2 id="DQL">DQL</h2><blockquote><p>Data Query Language  数据查询语言，用来查询数据库中表的记录</p></blockquote><p>在实际开发和业务中，查询也是最常用的</p><p>语法：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span></span><br><span class="line">字段列表</span><br><span class="line"><span class="keyword">FROM</span></span><br><span class="line">表名列表</span><br><span class="line"><span class="keyword">WHERE</span></span><br><span class="line">条件列表</span><br><span class="line"><span class="keyword">GROUP</span> <span class="keyword">BY</span></span><br><span class="line">分组字段列表</span><br><span class="line"><span class="keyword">HAVING</span></span><br><span class="line">分组后条件列表</span><br><span class="line"><span class="keyword">ORDER</span> <span class="keyword">BY</span></span><br><span class="line">排序字段列表</span><br><span class="line">LIMIT</span><br><span class="line">分页参数</span><br></pre></td></tr></table></figure><p><strong>这一语法非常重要，涉及到很多的知识</strong>。</p><h3 id="基础查询">基础查询</h3><ol><li>查询多个字段</li></ol><p>语法：<code>SELECT 字段1, 字段2, 字段3 ... FROM 表名 ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 从emps表中查询employee_id、email和hire_date字段的数据</span></span><br><span class="line"><span class="keyword">select</span> employee_id,email,hire_date <span class="keyword">from</span> emps;</span><br><span class="line"><span class="comment">-- 如果要查询所有字段，可以使用select * from 表明，但是在开发规范中一般会规定不使用* 而用字段提高效率。</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/6HKDnIRyjXG9342.png" alt="004_DQL_01.png"></p><ol start="2"><li>字段设置别名</li></ol><p>语法：<code>SELECT 字段1 [ [AS] 别名1 ] , 字段2 [ [AS] 别名2 ] ... FROM 表名;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 给字段取别名 建议带上as</span></span><br><span class="line"><span class="keyword">select</span> employee_id <span class="keyword">as</span> <span class="string">&#x27;职工号&#x27;</span> <span class="keyword">from</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/JqUpDIcVmO9jRN4.png" alt="004_DQL_02.png"></p><ol start="3"><li>去除重复数据</li></ol><p>语法：<code>SELECT DISTINCT 字段列表 FROM 表名;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询字段数据且不重复</span></span><br><span class="line"><span class="keyword">select</span> <span class="keyword">distinct</span> job_id <span class="string">&#x27;工作岗位&#x27;</span> <span class="keyword">from</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/W9ABeQaI7YpM8Jt.png" alt="004_DQL_03.png"></p><h3 id="条件查询">条件查询</h3><p>语法：<code>SELECT 字段列表 FROM 表名 WHERE 条件列表 ;  </code><br>常见的比较运算符和逻辑运算符如下</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">比较运算符</button><button type="button" class="tab">逻辑运算符</button></div><div class="tab-contents"><div class="tab-item-content active"><table><thead><tr><th>比较运算符</th><th>功能</th></tr></thead><tbody><tr><td>&gt;</td><td>大于</td></tr><tr><td>&gt;=</td><td>大于等于</td></tr><tr><td>&lt;</td><td>小于</td></tr><tr><td>&lt;=</td><td>小于等于</td></tr><tr><td>=</td><td>等于</td></tr><tr><td>&lt;&gt; 或 !=</td><td>不等于</td></tr><tr><td>BETWEEN … AND …</td><td>在某个范围之内(含最小、最大值)</td></tr><tr><td>IN(…)</td><td>在in之后的列表中的值，多选一</td></tr><tr><td>LIKE 占位符</td><td>模糊匹配(_匹配单个字符, %匹配任意个字符)</td></tr><tr><td>IS NULL</td><td>是NULL</td></tr></tbody></table></div><div class="tab-item-content"><table><thead><tr><th>逻辑运算符</th><th>功能</th></tr></thead><tbody><tr><td>AND 或 &amp;&amp;</td><td>并且 (多个条件同时成立)</td></tr><tr><td>OR 或 ||</td><td>或者 (多个条件任意一个成立)</td></tr><tr><td>NOT 或 !</td><td>非 , 不是</td></tr></tbody></table></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 条件查询 </span></span><br><span class="line"><span class="comment">-- 从emps表中查询员工id为100的员工所有信息</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps <span class="keyword">where</span> employee_id <span class="operator">=</span> <span class="number">100</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ty8h4JOMkUnIWLu.png" alt="004_DQL_04.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 多个字段的限制</span></span><br><span class="line"><span class="comment">-- 从emps表中查询工资等于2500且部门id为50的员工所有信息</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps <span class="keyword">where</span> salary <span class="operator">=</span> <span class="number">2500</span> <span class="keyword">and</span> department_id <span class="operator">=</span> <span class="number">50</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/VfTGd3ZY87qpgH2.png" alt="004_DQL_05.png"></p><p>字符串的查询：<strong>模糊匹配</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询姓最后一个字符是a的数据</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps <span class="keyword">where</span> emps.first_name <span class="keyword">like</span> <span class="string">&#x27;%a&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/aE43p5XeAfS7RBM.png" alt="004_DQL_06.png"></p><h3 id="聚合函数">聚合函数</h3><p>概念：将一列数据作为整体进行数学运算，就像是Excel的函数库<br>常见的聚合函数</p><table><thead><tr><th>函数</th><th>功能</th></tr></thead><tbody><tr><td>count</td><td>统计数量</td></tr><tr><td>max</td><td>最大值</td></tr><tr><td>min</td><td>最小值</td></tr><tr><td>avg</td><td>平均值</td></tr><tr><td>sum</td><td>求和</td></tr></tbody></table><p>语法:<code>SELECT 聚合函数(字段列表) FROM 表名  ;</code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 统计有commission_pct字段数据的个数 注意null是不参与聚合函数的运算的</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">count</span>(commission_pct) <span class="keyword">from</span> emps;</span><br><span class="line"><span class="comment">-- 统计总记录数 用count(1)同理</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/K2whiGnPMvR1Xfs.png" alt="004_DQL_07.png"></p><h3 id="分组查询">分组查询</h3><p>语法：<code>SELECT 字段列表 FROM 表名 [ WHERE 条件 ] GROUP BY 分组字段名 [ HAVING 分组后过滤条件 ];  </code><br>where与having区别</p><ol><li>执行时机不同：where是分组之前进行过滤，不满足where条件，不参与分组；而having是分组<br>之后对结果进行过滤。</li><li>判断条件不同：where不能对聚合函数进行判断，而having可以</li></ol><blockquote><ol><li>分组之后，查询的字段一般为聚合函数和分组字段，查询其他字段无任何意义。</li><li>执行顺序: where &gt; 聚合函数 &gt; having 。</li><li>支持多字段分组, 具体语法为 : group by columnA,columnB</li></ol></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 统计不同工资对应的人员数量</span></span><br><span class="line"><span class="comment">-- 先对工资分组，然后再统计每一组工资员工的数量</span></span><br><span class="line"><span class="keyword">select</span> salary,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> emps <span class="keyword">group</span> <span class="keyword">by</span> salary;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/CFOLIrYm4cp3uWU.png" alt="004_DQL_08.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 根据部门分组，统计各部门的平均工资</span></span><br><span class="line"><span class="keyword">select</span> department_id,<span class="built_in">avg</span>(salary) <span class="keyword">from</span> emps <span class="keyword">group</span> <span class="keyword">by</span> department_id;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/YGoMWyUF2BlSA6c.png" alt="004_DQL_09.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询工资小于等于4000的员工，并根据部门分组，获取员工数量大于等于2的部门id</span></span><br><span class="line"><span class="keyword">select</span> department_id,<span class="built_in">count</span>(<span class="operator">*</span>) <span class="keyword">from</span> emps <span class="keyword">where</span> salary <span class="operator">&lt;=</span><span class="number">4000</span> <span class="keyword">group</span> <span class="keyword">by</span> department_id <span class="keyword">having</span> <span class="built_in">count</span>(<span class="operator">*</span>) <span class="operator">&gt;=</span><span class="number">2</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/oj9OcCwBynfXpFE.png" alt="004_DQL_10.png"></p><h3 id="排序查询">排序查询</h3><p>语法：<code>SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1 , 字段2 排序方式2 ;  </code>asc为升序(默认)，desc为降序</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 根据入职时间升序排序</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps <span class="keyword">order</span> <span class="keyword">by</span> hire_date;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/sZwq3O7CiDfP4FB.png" alt="004_DQL_11.png"></p><blockquote><p>如果是多字段排序，当第一个字段相同的时候才会按照第二个字段进行排序</p></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 先按照工资排序，年龄相同就按入职时间降序排序</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps <span class="keyword">order</span> <span class="keyword">by</span> salary <span class="keyword">asc</span>,hire_date <span class="keyword">desc</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/NlIefXg8oWVKnuD.png" alt="004_DQL_12.png"></p><h3 id="分页查询">分页查询</h3><p>就是在浏览网页的时候经常会有的分页条</p><p>语法：<code>SELECT 字段列表 FROM 表名 LIMIT 起始索引, 查询记录数 ;  </code></p><blockquote><p>• 起始索引从0开始，起始索引 = （查询页码 - 1）* 每页显示记录数。<br>• 分页查询是数据库的方言，不同的数据库有不同的实现，MySQL中是LIMIT。<br>• 如果查询的是第一页数据，起始索引可以省略，直接简写为 limit 10。</p></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 分页查询-尤其在电商网站上使用较多</span></span><br><span class="line"><span class="comment">-- 查询第一页员工数据，每一页显示10条数据,注意经典索引从0开始</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emps limit <span class="number">0</span>,<span class="number">10</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/RMaPj3FlQGJBLUS.png" alt="004_DQL_13.png"></p><p><strong>启示</strong>：<u>用英语“从句”的思维理解mysql语句执行的先后顺序</u></p><p>举例：查询性别为男，年龄在20-40岁之间(含)的前5个员工信息，对查询的结果按年龄升序排列，如果年龄相同就按照入职时间排序。</p><p>这里的关键在于找到“主句”-查询信息，谁的信息呢？，前面的修饰语就是“男”、“年龄”和“前五个”，后面的对……句都是状语，一般放在后面的，所以先写出<code>select * from emp where gender = '男' and age between 20 and 40</code>的语句，但是好像没有“前五个”，聪明的你应该发现前五个就是分页查询，按每页5个不就是能找到前五个了吗。那就是limit 5，由于mysql的特性，limit要放在句子的最后面。我们再考虑“状语”，关键词是“排序”，那就在前面语句的基础上再筛选 即<code>order by age asc,entrydate asc limit 5;</code>组合起来就是完整的语句了。执行顺序是 <strong>from-&gt;where-&gt;group by-&gt;select-&gt;having-&gt;order by-&gt;limit.</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> gender <span class="operator">=</span> <span class="string">&#x27;男&#x27;</span> <span class="keyword">and</span> age <span class="keyword">between</span> <span class="number">20</span> <span class="keyword">and</span> <span class="number">40</span> <span class="keyword">order</span> <span class="keyword">by</span> age <span class="keyword">asc</span> ,endrydate <span class="keyword">asc</span> limit <span class="number">5</span></span><br></pre></td></tr></table></figure><h2 id="DCL">DCL</h2><blockquote><p>Data Control Languages  数据控制语言</p></blockquote><p>概念：用来管理数据库用户、控制数据库的访问权限</p><h3 id="管理用户">管理用户</h3><ol><li>查询用户</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询用户</span></span><br><span class="line">USE MYSQL;</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> mysql.user; </span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/AgT2wMblaQ6tXNd.png" alt="005_DCL_01.png"></p><p>其中 Host代表当前用户访问的主机, 如果为localhost, 仅代表只能够在当前本机访问，是不可以远程访问的(用于远程访问的一般是Linux上的MySQL)。 User代表的是访问该数据库的用户名。在MySQL中需要通过Host和User来唯一标识一个用户</p><ol start="2"><li>创建用户</li></ol><p>语法：<code>CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建用户，只能够在当前主机上访问(localhost)</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">user</span> <span class="string">&#x27;jerry&#x27;</span>@<span class="string">&#x27;localhost&#x27;</span> identified <span class="keyword">by</span> <span class="string">&#x27;123456&#x27;</span>;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 创建用户，可以在任意主机上访问,主要是在虚拟机上使用的较多</span></span><br><span class="line"><span class="keyword">create</span> <span class="keyword">user</span> <span class="string">&#x27;tom&#x27;</span>@<span class="string">&#x27;%&#x27;</span> identified <span class="keyword">by</span> <span class="string">&#x27;123456&#x27;</span>;</span><br></pre></td></tr></table></figure><ol start="3"><li>修改用户密码</li></ol><p>语法：<code>ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码' ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 修改用户密码</span></span><br><span class="line"><span class="keyword">alter</span> <span class="keyword">user</span> <span class="string">&#x27;jerry&#x27;</span>@<span class="string">&#x27;localhost&#x27;</span> identified <span class="keyword">with</span> mysql_native_password <span class="keyword">by</span> <span class="string">&#x27;1234&#x27;</span>;</span><br></pre></td></tr></table></figure><ol start="4"><li>删除用户</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除用户</span></span><br><span class="line"><span class="keyword">drop</span> <span class="keyword">user</span> <span class="string">&#x27;jerry&#x27;</span>@<span class="string">&#x27;localhost&#x27;</span>;</span><br><span class="line"><span class="keyword">drop</span> <span class="keyword">user</span> <span class="string">&#x27;tom&#x27;</span>@<span class="string">&#x27;%&#x27;</span>;</span><br></pre></td></tr></table></figure><blockquote><ol><li>在MySQL中需要通过用户名@主机名的方式，来唯一标识一个用户</li><li>主机名可以使用 % 通配</li></ol></blockquote><h3 id="权限控制">权限控制</h3><p>分类</p><table><thead><tr><th>权限</th><th>说明</th></tr></thead><tbody><tr><td>ALL, ALL PRIVILEGES</td><td>所有权限</td></tr><tr><td>SELECT</td><td>查询数据</td></tr><tr><td>INSERT</td><td>插入数据</td></tr><tr><td>UPDATE</td><td>修改数据</td></tr><tr><td>DELETE</td><td>删除数据</td></tr><tr><td>ALTER</td><td>修改表</td></tr><tr><td>DROP</td><td>删除数据库/表/视图</td></tr><tr><td>CREATE</td><td>创建数据库/表</td></tr></tbody></table><p>具体的权限描述和其他的请查看官方网站<a href="https://dev.mysql.com">https://dev.mysql.com</a>；不会就找中文版的文档吧(ㆆᴗㆆ)</p><ol><li>查询权限</li></ol><p>语法：<code>SHOW GRANTS FOR '用户名'@'主机名' ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询权限</span></span><br><span class="line"><span class="keyword">show</span> grants <span class="keyword">for</span> <span class="string">&#x27;jerry&#x27;</span>@<span class="string">&#x27;localhost&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/arPxdTF5kM6mYHq.png" alt="005_DCL_02.png"></p><ol start="2"><li>授予权限</li></ol><p>很重要，远程登录的时候无法增删查改很大程度上都是因为没有授予相应的权限。</p><p>语法：<code>GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机名';  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 授予权限 将test1数据库的所有表对jerry用户开放 *代表所有</span></span><br><span class="line"><span class="keyword">grant</span> <span class="keyword">all</span> <span class="keyword">on</span> test1.<span class="operator">*</span> <span class="keyword">to</span> <span class="string">&#x27;jerry&#x27;</span>@<span class="string">&#x27;localhost&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ZXyb6tPOscIwghz.png" alt="005_DCL_03.png"></p><ol start="3"><li>撤销权限</li></ol><p>语法：<code>REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机名';  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 撤销权限</span></span><br><span class="line"><span class="keyword">revoke</span> <span class="keyword">all</span> <span class="keyword">on</span>  test1.<span class="operator">*</span> <span class="keyword">from</span> <span class="string">&#x27;jerry&#x27;</span>@<span class="string">&#x27;localhost&#x27;</span>;</span><br></pre></td></tr></table></figure><blockquote><ol><li>多个权限之间用逗号连接</li><li>授权时数据库名和表名可以使用 * 进行通配，代表所有。</li></ol></blockquote><hr><h2 id="函数">函数</h2><h3 id="字符串函数">字符串函数</h3><p>常见的字符串函数如下</p><table><thead><tr><th>函数</th><th>功能</th></tr></thead><tbody><tr><td>CONCAT(S1,S2,…Sn)</td><td>字符串拼接，将S1，S2，… Sn拼接成一个字符串</td></tr><tr><td>LOWER(str)</td><td>将字符串str全部转为小写</td></tr><tr><td>UPPER(str)</td><td>将字符串str全部转为大写</td></tr><tr><td>LPAD(str,n,pad)</td><td>左填充，用字符串pad对str的左边进行填充，达到n个字符 串长度</td></tr><tr><td>RPAD(str,n,pad)</td><td>右填充，用字符串pad对str的右边进行填充，达到n个字符 串长度</td></tr><tr><td>TRIM(str)</td><td>去掉字符串头部和尾部的空格</td></tr><tr><td>SUBSTRING(str,start,len)</td><td>返回从字符串str从start位置起的len个长度的字符串</td></tr></tbody></table><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 字符串拼接</span></span><br><span class="line"><span class="keyword">select</span> concat(<span class="string">&#x27;hello&#x27;</span>,<span class="string">&#x27;mysql&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/dG8FHazo6M5NYVI.png" alt="006_函数_01.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 大小写转换</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">lower</span>(<span class="string">&#x27;HELLO&#x27;</span>);</span><br><span class="line"><span class="keyword">select</span> <span class="built_in">upper</span>(<span class="string">&#x27;hello&#x27;</span>);</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 左填充与右填充 常用于日期、编号等的数据</span></span><br><span class="line"><span class="keyword">select</span> lpad(<span class="string">&#x27;01&#x27;</span>,<span class="number">5</span>,<span class="string">&#x27;-&#x27;</span>);</span><br><span class="line"><span class="keyword">select</span> rpad(<span class="string">&#x27;01&#x27;</span>,<span class="number">5</span>,<span class="string">&#x27;-&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/Fxr3X5GZCflwDRA.png" alt="006_函数_02.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 去除空格</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">trim</span>(<span class="string">&#x27; Hello MySQL &#x27;</span>);</span><br><span class="line"><span class="comment">-- 截取字符串 注意索引从1开始</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">substring</span>(<span class="string">&#x27;hello mysql&#x27;</span>,<span class="number">1</span>,<span class="number">5</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/tQM4f2WhCjdGkya.png" alt="006_函数_03.png"></p><h3 id="数值函数">数值函数</h3><table><thead><tr><th>函数</th><th>功能</th></tr></thead><tbody><tr><td>CEIL(x)</td><td>向上取整</td></tr><tr><td>FLOOR(x)</td><td>向下取整</td></tr><tr><td>MOD(x,y)</td><td>返回x/y的模</td></tr><tr><td>RAND()</td><td>返回0~1内的随机数</td></tr><tr><td>ROUND(x,y)</td><td>求参数x的四舍五入的值，保留y位小数</td></tr></tbody></table><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 数值函数 就是编程语言中常见的函数</span></span><br><span class="line"><span class="comment">-- 向上取整，</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">ceil</span>(<span class="number">1.1</span>);<span class="comment">-- 结果为2</span></span><br><span class="line"><span class="comment">-- 向下取整-即保留整数位</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">floor</span>(<span class="number">1.9</span>);</span><br><span class="line"><span class="comment">-- 取模</span></span><br><span class="line"><span class="keyword">select</span> <span class="built_in">mod</span>(<span class="number">3</span>,<span class="number">2</span>);</span><br><span class="line"><span class="comment">-- 随机数 不写默认是0-1的数</span></span><br><span class="line"><span class="keyword">select</span> rand();</span><br><span class="line"><span class="comment">-- 四舍五入+保留小数位数</span></span><br><span class="line"><span class="keyword">select</span> round(<span class="number">2.35</span>,<span class="number">2</span>);</span><br></pre></td></tr></table></figure><p><strong>生成一个六位数的随机验证码</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- rand函数生成0-1的随机小数</span></span><br><span class="line"><span class="keyword">select</span> lpad(round(rand()<span class="operator">*</span><span class="number">1000000</span>,<span class="number">0</span>),<span class="number">6</span>,<span class="string">&#x27;0&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/gpo3SsexIrOJt8F.png" alt="006_函数_04.png"></p><h3 id="日期函数">日期函数</h3><table><thead><tr><th>函数</th><th>功能</th></tr></thead><tbody><tr><td>CURDATE()</td><td>返回当前日期</td></tr><tr><td>CURTIME()</td><td>返回当前时间</td></tr><tr><td>NOW()</td><td>返回当前日期和时间</td></tr><tr><td>YEAR(date)</td><td>获取指定date的年份</td></tr><tr><td>MONTH(date)</td><td>获取指定date的月份</td></tr><tr><td>DAY(date)</td><td>获取指定date的日期</td></tr><tr><td>DATE_ADD(date, INTERVAL expr type)</td><td>返回一个日期/时间值加上一个时间间隔expr后的 时间值</td></tr><tr><td>DATEDIFF(date1,date2)</td><td>返回起始时间date1 和 结束时间date2之间的天 数</td></tr></tbody></table><p>示例</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 英语中date表示日期，time表示具体的时间</span></span><br><span class="line"><span class="comment">-- 当前日期</span></span><br><span class="line"><span class="keyword">select</span> curdate();</span><br><span class="line"><span class="comment">-- 当前时间</span></span><br><span class="line"><span class="keyword">select</span> curtime();</span><br><span class="line"><span class="comment">-- 当前日期+时间</span></span><br><span class="line"><span class="keyword">select</span> now();</span><br><span class="line"><span class="comment">-- 年月日函数</span></span><br><span class="line"><span class="keyword">select</span> <span class="keyword">day</span>(now());</span><br><span class="line"><span class="comment">-- “增加”时间</span></span><br><span class="line"><span class="keyword">select</span> date_add(now(),<span class="type">interval</span> <span class="number">70</span> <span class="keyword">day</span>); # 这里的意思是在当前时间<span class="operator">+</span><span class="number">70</span>天</span><br></pre></td></tr></table></figure><p><strong>两时间之差：第一个参数-第二个参数</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 求2021-07-21与1921-07-21间隔的天数</span></span><br><span class="line"><span class="keyword">select</span> datediff(<span class="string">&#x27;2021-07-21&#x27;</span>,<span class="string">&#x27;1921-07-21&#x27;</span>);</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 查询所有员工的入职天数，并根据入职天数倒序排序</span></span><br><span class="line"><span class="keyword">select</span> first_name,datediff(curdate(),hire_date) <span class="keyword">as</span> <span class="string">&#x27;entrydays&#x27;</span> <span class="keyword">from</span> emps <span class="keyword">order</span> <span class="keyword">by</span> entrydays <span class="keyword">desc</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/3tp8Gyj2z4JYVcH.png" alt="006_函数_05.png"></p><h3 id="流程函数">流程函数</h3><blockquote><p>就是高级语言中的控制函数</p></blockquote><table><thead><tr><th>函数</th><th>功能</th></tr></thead><tbody><tr><td>IF(value , t , f)</td><td>如果value为true，则返回t，否则返回 f</td></tr><tr><td>IFNULL(value1 , value2)</td><td>如果value1不为空，返回value1，否则 返回value2</td></tr><tr><td>CASE WHEN [ val1 ] THEN [res1] … ELSE [ default ] END</td><td>如果val1为true，返回res1，… 否 则返回default默认值</td></tr><tr><td>CASE [ expr ] WHEN [ val1 ] THEN [res1] … ELSE [ default ] END</td><td>如果expr的值等于val1，返回 res1，… 否则返回default默认值</td></tr></tbody></table><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 流程控制函数 就是编程语言中的控制函数</span></span><br><span class="line"><span class="keyword">select</span> if(<span class="literal">true</span>,<span class="string">&#x27;OK&#x27;</span>,<span class="string">&#x27;error&#x27;</span>);</span><br><span class="line"><span class="comment">-- 判断是否为null</span></span><br><span class="line"><span class="keyword">select</span> ifnull(<span class="keyword">null</span>,<span class="string">&#x27;default&#x27;</span>);</span><br><span class="line"><span class="comment">-- 多选择分支</span></span><br><span class="line"><span class="keyword">select</span></span><br><span class="line">    name,</span><br><span class="line">    (<span class="keyword">case</span> note <span class="keyword">when</span> <span class="string">&#x27;novel&#x27;</span> <span class="keyword">then</span> <span class="string">&#x27;小说&#x27;</span> <span class="keyword">when</span> <span class="string">&#x27;drama&#x27;</span> <span class="keyword">then</span> <span class="string">&#x27;戏剧&#x27;</span> <span class="keyword">else</span> <span class="string">&#x27;其他类型&#x27;</span><span class="keyword">end</span>) <span class="keyword">as</span> <span class="string">&#x27;图书表&#x27;</span></span><br><span class="line"><span class="keyword">from</span> books;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/gYBwr9Z78fcEhtW.png" alt="006_函数_06.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 案例 按照不同的工资范围给予对应员工评价</span></span><br><span class="line"><span class="keyword">select</span></span><br><span class="line">    first_name,</span><br><span class="line">    (<span class="keyword">case</span> <span class="keyword">when</span> salary <span class="operator">&gt;=</span><span class="number">10000</span> <span class="keyword">then</span> <span class="string">&#x27;优秀&#x27;</span> <span class="keyword">when</span> salary <span class="operator">&gt;=</span><span class="number">6000</span> <span class="keyword">then</span> <span class="string">&#x27;还行&#x27;</span> <span class="keyword">else</span> <span class="string">&#x27;加把劲&#x27;</span> <span class="keyword">end</span>) <span class="string">&#x27;工资表&#x27;</span></span><br><span class="line"><span class="keyword">from</span> emps;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/RSnAFzK42NJxkTC.png" alt="006_函数_07.png"></p><hr><h2 id="约束-constraint">约束(constraint)</h2><h3 id="一般约束">一般约束</h3><p>概念：约束是作用于表中字段上的规则，用于限制存储在表中的数据。</p><table><thead><tr><th>约束</th><th>描述</th><th>关键字</th></tr></thead><tbody><tr><td>非空约束</td><td>限制该字段的数据不能为null</td><td>NOT NULL</td></tr><tr><td>唯一约束</td><td>保证该字段的所有数据都是唯一、不重复的</td><td>UNIQUE</td></tr><tr><td>主键约束</td><td>主键是一行数据的唯一标识，要求非空且唯一</td><td>PRIMARY KEY</td></tr><tr><td>默认约束</td><td>保存数据时，如果未指定该字段的值，则采用默认值</td><td>DEFAULT</td></tr><tr><td>检查约束(8.0.16版本之后)</td><td>保证字段值满足某一个条件</td><td>CHECK</td></tr><tr><td>外键约束</td><td>用来让两张表的数据之间建立连接，保证数据的一致 性和完整性</td><td>FOREIGN KEY</td></tr></tbody></table><blockquote><p>在创建表过程或者已经创建均可以添加约束</p></blockquote><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 案例</span></span><br><span class="line"><span class="keyword">create table</span> <span class="keyword">user</span>(</span><br><span class="line">    id <span class="type">int</span> <span class="keyword">primary key</span> auto_increment comment <span class="string">&#x27;主键&#x27;</span>,</span><br><span class="line">    name <span class="type">varchar</span>(<span class="number">10</span>) <span class="keyword">not null</span> <span class="keyword">unique</span> comment <span class="string">&#x27;姓名&#x27;</span>,</span><br><span class="line">    age <span class="type">int</span> <span class="keyword">check</span> ( age <span class="operator">&gt;</span> <span class="number">0</span> <span class="operator">&amp;&amp;</span> age <span class="operator">&lt;=</span><span class="number">120</span> ) comment <span class="string">&#x27;年龄&#x27;</span>,</span><br><span class="line">    status <span class="type">char</span>(<span class="number">1</span>) <span class="keyword">default</span> <span class="string">&#x27;1&#x27;</span> comment <span class="string">&#x27;状态&#x27;</span>,</span><br><span class="line">    gender <span class="type">char</span>(<span class="number">1</span>) comment <span class="string">&#x27;性别&#x27;</span></span><br><span class="line">) comment <span class="string">&#x27;用户表&#x27;</span>;</span><br><span class="line"><span class="comment">-- 插入数据 主键自增不需要添加数据</span></span><br><span class="line"><span class="comment">-- 同理可以在图形化界面添加对应的约束</span></span><br><span class="line"><span class="keyword">insert into</span> <span class="keyword">user</span>(name,age,status,gender) <span class="keyword">value</span> (<span class="string">&#x27;Tom1&#x27;</span>,<span class="string">&#x27;19&#x27;</span>,<span class="string">&#x27;1&#x27;</span>,<span class="string">&#x27;男&#x27;</span>),(<span class="string">&#x27;Tom2&#x27;</span>,<span class="string">&#x27;25&#x27;</span>,<span class="string">&#x27;0&#x27;</span>,<span class="string">&#x27;男&#x27;</span>);</span><br><span class="line"><span class="keyword">insert into</span> <span class="keyword">user</span>(name,age,status,gender) <span class="keyword">value</span> (<span class="keyword">null</span>,<span class="string">&#x27;19&#x27;</span>,<span class="string">&#x27;1&#x27;</span>,<span class="string">&#x27;男&#x27;</span>);</span><br></pre></td></tr></table></figure><p>第12行代码异常执行，不符合约束的数据不会添加</p><p><img src="https://s2.loli.net/2024/11/26/bQmP2UBw3MkD5zC.png" alt="007_约束_01.png"></p><h3 id="外键约束">外键约束</h3><p>概念：用来让两张表的数据之间建立连接，从而保证数据的一致性和完整性</p><ol><li>添加外键</li></ol><p>语法</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 在创建表的时候添加</span></span><br><span class="line"><span class="keyword">CREATE TABLE</span> 表名(</span><br><span class="line">字段名 数据类型,</span><br><span class="line">...</span><br><span class="line">[<span class="keyword">CONSTRAINT</span>] [外键名称] <span class="keyword">FOREIGN KEY</span> (外键字段名) <span class="keyword">REFERENCES</span> 主表 (主表列名)</span><br><span class="line">)</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 在修改表的时候添加</span></span><br><span class="line"><span class="keyword">ALTER TABLE</span> 表名 <span class="keyword">ADD CONSTRAINT</span> 外键名称 <span class="keyword">FOREIGN KEY</span> (外键字段名) <span class="keyword">REFERENCES</span> 主表 (主表列名) ;</span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 让两张表的数据之间建立联系，从而保证数据一致</span></span><br><span class="line"><span class="comment">-- 具有外键的表成为子表，而关联的表称为父表</span></span><br><span class="line"><span class="comment">-- 准备数据</span></span><br><span class="line"><span class="keyword">create table</span> dept(</span><br><span class="line">                     id   <span class="type">int</span> auto_increment comment <span class="string">&#x27;ID&#x27;</span> <span class="keyword">primary key</span>,</span><br><span class="line">                     name <span class="type">varchar</span>(<span class="number">50</span>) <span class="keyword">not null</span> comment <span class="string">&#x27;部门名称&#x27;</span></span><br><span class="line">)comment <span class="string">&#x27;部门表&#x27;</span>;</span><br><span class="line"><span class="keyword">INSERT INTO</span> dept (id, name) <span class="keyword">VALUES</span> (<span class="number">1</span>, <span class="string">&#x27;研发部&#x27;</span>), (<span class="number">2</span>, <span class="string">&#x27;市场部&#x27;</span>),(<span class="number">3</span>, <span class="string">&#x27;财务部&#x27;</span>), (<span class="number">4</span>, <span class="string">&#x27;销售部&#x27;</span>), (<span class="number">5</span>, <span class="string">&#x27;总经办&#x27;</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">create table</span> emp(</span><br><span class="line">                    id  <span class="type">int</span> auto_increment comment <span class="string">&#x27;ID&#x27;</span> <span class="keyword">primary key</span>,</span><br><span class="line">                    name <span class="type">varchar</span>(<span class="number">50</span>) <span class="keyword">not null</span> comment <span class="string">&#x27;姓名&#x27;</span>,</span><br><span class="line">                    age  <span class="type">int</span> comment <span class="string">&#x27;年龄&#x27;</span>,</span><br><span class="line">                    job <span class="type">varchar</span>(<span class="number">20</span>) comment <span class="string">&#x27;职位&#x27;</span>,</span><br><span class="line">                    salary <span class="type">int</span> comment <span class="string">&#x27;薪资&#x27;</span>,</span><br><span class="line">                    entrydate <span class="type">date</span> comment <span class="string">&#x27;入职时间&#x27;</span>,</span><br><span class="line">                    managerid <span class="type">int</span> comment <span class="string">&#x27;直属领导ID&#x27;</span>,</span><br><span class="line">                    dept_id <span class="type">int</span> comment <span class="string">&#x27;部门ID&#x27;</span></span><br><span class="line">)comment <span class="string">&#x27;员工表&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">INSERT INTO</span> emp (id, name, age, job,salary, entrydate, managerid, dept_id) <span class="keyword">VALUES</span></span><br><span class="line">                                                                               (<span class="number">1</span>, <span class="string">&#x27;金庸&#x27;</span>, <span class="number">66</span>, <span class="string">&#x27;总裁&#x27;</span>,<span class="number">20000</span>, <span class="string">&#x27;2000-01-01&#x27;</span>, <span class="keyword">null</span>,<span class="number">5</span>),(<span class="number">2</span>, <span class="string">&#x27;张无忌&#x27;</span>, <span class="number">20</span>, <span class="string">&#x27;项目经理&#x27;</span>,<span class="number">12500</span>, <span class="string">&#x27;2005-12-05&#x27;</span>, <span class="number">1</span>,<span class="number">1</span>),</span><br><span class="line">                                                                               (<span class="number">3</span>, <span class="string">&#x27;杨逍&#x27;</span>, <span class="number">33</span>, <span class="string">&#x27;开发&#x27;</span>, <span class="number">8400</span>,<span class="string">&#x27;2000-11-03&#x27;</span>, <span class="number">2</span>,<span class="number">1</span>),(<span class="number">4</span>, <span class="string">&#x27;韦一笑&#x27;</span>, <span class="number">48</span>, <span class="string">&#x27;开发&#x27;</span>,<span class="number">11000</span>, <span class="string">&#x27;2002-02-05&#x27;</span>, <span class="number">2</span>,<span class="number">1</span>),</span><br><span class="line">                                                                               (<span class="number">5</span>, <span class="string">&#x27;常遇春&#x27;</span>, <span class="number">43</span>, <span class="string">&#x27;开发&#x27;</span>,<span class="number">10500</span>, <span class="string">&#x27;2004-09-07&#x27;</span>, <span class="number">3</span>,<span class="number">1</span>),(<span class="number">6</span>, <span class="string">&#x27;小昭&#x27;</span>, <span class="number">19</span>, <span class="string">&#x27;程序员鼓励师&#x27;</span>,<span class="number">6600</span>, <span class="string">&#x27;2004-10-12&#x27;</span>, <span class="number">2</span>,<span class="number">1</span>);                                                                               </span><br></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 添加外键</span></span><br><span class="line"><span class="comment">-- 为emp表中的dept_id字段添加外键约束，关联dept表中的主键id，并将外键命名为fk_emp_dept_id</span></span><br><span class="line"><span class="keyword">alter table</span> emp <span class="keyword">add constraint</span> fk_emp_dept_id <span class="keyword">foreign key</span> (dept_id) <span class="keyword">references</span> dept(id);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/ZKmX3cShaUJt6bC.png" alt="007_约束_02.png"></p><ol start="2"><li>删除外键</li></ol><p>语法：<code>ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 删除外键</span></span><br><span class="line"><span class="keyword">alter table</span> emp <span class="keyword">drop</span> <span class="keyword">foreign key</span> fk_emp_dept_id;</span><br></pre></td></tr></table></figure><ol start="3"><li>删除/更新行为</li></ol><p>概念：添加了外键之后，再删除父表数据时产生的约束行为，我们就称为删除/更新行为<br>分类</p><table><thead><tr><th>行为</th><th>说明</th></tr></thead><tbody><tr><td>NO ACTION</td><td>当在父表中删除/更新对应记录时，首先检查该记录是否有对应外键，如果有则不 允许删除/更新。 (与 RESTRICT 一致) 默认行为</td></tr><tr><td>RESTRICT</td><td>当在父表中删除/更新对应记录时，首先检查该记录是否有对应外键，如果有则不 允许删除/更新。 (与 NO ACTION 一致) 默认行为</td></tr><tr><td>CASCADE</td><td>当在父表中删除/更新对应记录时，首先检查该记录是否有对应外键，如果有，则 也删除/更新外键在子表中的记录。</td></tr><tr><td>SET NULL</td><td>当在父表中删除对应记录时，首先检查该记录是否有对应外键，如果有则设置子表 中该外键值为null（这就要求该外键允许取null）。</td></tr><tr><td>SET DEFAULT</td><td>父表有变更时，子表将外键列设置成一个默认的值 (Innodb不支持)</td></tr></tbody></table><p>语法：<code>ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段) REFERENCES 主表名 (主表字段名) ON UPDATE CASCADE ON DELETE CASCADE;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 外键更新 父表更新时子表也会更新</span></span><br><span class="line"><span class="comment">-- on update 后面跟cascade 表明在更新的时候首先检查该记录是否有对应外键，如果有，则更新外键在子表中的记录。</span></span><br><span class="line"><span class="comment">-- on delete 后面跟cascade 表明在删除的时候首先检查该记录是否有对应外键，如果有，则删除外键在子表中的记录。</span></span><br><span class="line"><span class="keyword">alter table</span> emp <span class="keyword">add constraint</span> fk_emp_dept_id <span class="keyword">foreign key</span> (dept_id) <span class="keyword">references</span> dept(id) <span class="keyword">on</span> <span class="keyword">update</span> cascade <span class="keyword">on</span> <span class="keyword">delete</span> cascade ;</span><br></pre></td></tr></table></figure><blockquote><p>在一般的业务系统中，一般不会 修改一张表的主键值</p></blockquote><hr><h2 id="多表查询">多表查询</h2><p>概念:从多张表中查询数据</p><h3 id="多表关系">多表关系</h3><p>分类</p><ul><li>一对多（多对一）</li><li>多对多</li><li>一对一</li></ul><p>示例：<strong>多对多</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 表之间的联系，一对一，一对多(多对一),多对多</span></span><br><span class="line"><span class="comment">-- 一对多(一个部门对应多个员工，一个员工对应一个部门)</span></span><br><span class="line"><span class="comment">-- 多对多(比如学生与课程)</span></span><br><span class="line"><span class="comment">-- 一对一常用于单表拆分</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 多对多演示</span></span><br><span class="line"><span class="keyword">create table</span> student(</span><br><span class="line">                        id <span class="type">int</span> auto_increment <span class="keyword">primary key</span> comment <span class="string">&#x27;主键ID&#x27;</span>,</span><br><span class="line">                        name <span class="type">varchar</span>(<span class="number">10</span>) comment <span class="string">&#x27;姓名&#x27;</span>,</span><br><span class="line">                        <span class="keyword">no</span> <span class="type">varchar</span>(<span class="number">10</span>) comment <span class="string">&#x27;学号&#x27;</span></span><br><span class="line">) comment <span class="string">&#x27;学生表&#x27;</span>;</span><br><span class="line"><span class="keyword">insert into</span> student <span class="keyword">values</span> (<span class="keyword">null</span>, <span class="string">&#x27;黛绮丝&#x27;</span>, <span class="string">&#x27;2000100101&#x27;</span>),(<span class="keyword">null</span>, <span class="string">&#x27;谢逊&#x27;</span>, <span class="string">&#x27;2000100102&#x27;</span>),(<span class="keyword">null</span>, <span class="string">&#x27;殷天正&#x27;</span>, <span class="string">&#x27;2000100103&#x27;</span>),(<span class="keyword">null</span>, <span class="string">&#x27;韦一笑&#x27;</span>, <span class="string">&#x27;2000100104&#x27;</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">create table</span> course(</span><br><span class="line">                       id <span class="type">int</span> auto_increment <span class="keyword">primary key</span> comment <span class="string">&#x27;主键ID&#x27;</span>,</span><br><span class="line">                       name <span class="type">varchar</span>(<span class="number">10</span>) comment <span class="string">&#x27;课程名称&#x27;</span></span><br><span class="line">) comment <span class="string">&#x27;课程表&#x27;</span>;</span><br><span class="line"><span class="keyword">insert into</span> course <span class="keyword">values</span> (<span class="keyword">null</span>, <span class="string">&#x27;Java&#x27;</span>), (<span class="keyword">null</span>, <span class="string">&#x27;PHP&#x27;</span>), (<span class="keyword">null</span> , <span class="string">&#x27;MySQL&#x27;</span>) , (<span class="keyword">null</span>, <span class="string">&#x27;Hadoop&#x27;</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">create table</span> student_course(</span><br><span class="line">                               id <span class="type">int</span> auto_increment comment <span class="string">&#x27;主键&#x27;</span> <span class="keyword">primary key</span>,</span><br><span class="line">                               studentid <span class="type">int</span> <span class="keyword">not null</span> comment <span class="string">&#x27;学生ID&#x27;</span>,</span><br><span class="line">                               courseid  <span class="type">int</span> <span class="keyword">not null</span> comment <span class="string">&#x27;课程ID&#x27;</span>,</span><br><span class="line">                               <span class="keyword">constraint</span> fk_courseid <span class="keyword">foreign key</span> (courseid) <span class="keyword">references</span> course (id),</span><br><span class="line">                               <span class="keyword">constraint</span> fk_studentid <span class="keyword">foreign key</span> (studentid) <span class="keyword">references</span> student (id)</span><br><span class="line">)comment <span class="string">&#x27;学生课程中间表&#x27;</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/8rdb7htSDO1QImg.png" alt="008_多表查询_01.png"></p><p>右键表-‘图表’-‘显示可视化’</p><p><img src="https://s2.loli.net/2024/11/26/jSLElGYd5wg9y73.png" alt="008_多表查询_02.png"></p><h3 id="多表查询-v2">多表查询</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 多表查询</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> test1.emp,dept;<span class="comment">-- 这样写出来的多表查询是笛卡尔积，考过计算机二级的同学应该学过</span></span><br></pre></td></tr></table></figure><p>简单来说，就是集合A与集合B的所有组合情况,显然这不是我们想要呈现的数据，消除笛卡尔积的方法就是让多个表以某种关系式连接起来(比如id相等)</p><p>笛卡尔积部分演示</p><p><img src="https://s2.loli.net/2024/11/26/ADj2WU5ZwXTGs97.png" alt="008_多表查询_03.png"></p><p>数学图演示</p><p><img src="https://s2.loli.net/2024/11/26/1UgqCXBSIoQndyP.png" alt="008_多表查询_04.png"></p><p>而我们不需要所有的组合情况，只需要按照一定的条件将多余的组合情况排除即可。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 消除笛卡尔积</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> test1.emp,dept <span class="keyword">where</span> emp.dept_id <span class="operator">=</span> dept.id;</span><br></pre></td></tr></table></figure><p>消除笛卡尔积之后</p><p><img src="https://s2.loli.net/2024/11/26/osut6nkyZ9SWpEr.png" alt="008_多表查询_05.png"></p><h3 id="连接分类">连接分类</h3><h4 id="内连接">内连接</h4><p>补图：用chartjs以韦恩图的形式展现连接</p><p>概念：就是求两张表的交集</p><ol><li>隐式内连接</li></ol><p>语法：<code>SELECT 字段列表 FROM 表1 , 表2 WHERE 条件 ... ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 内、外、自连接(和集合中的概念相似)，子查询</span></span><br><span class="line"><span class="comment">-- 内连接-查找两个表之间的交集</span></span><br><span class="line"><span class="comment">-- 隐式内连接(没有直接写inner join) 从两张表中找到id相同的并展示其在不同表的名字</span></span><br><span class="line"><span class="keyword">select</span> emp.name,dept.name <span class="keyword">from</span> test1.emp,dept <span class="keyword">where</span> emp.dept_id <span class="operator">=</span> dept.id;</span><br><span class="line"><span class="comment">-- 可以取别名缩短语句长度</span></span><br><span class="line"><span class="keyword">select</span> e.name,d.name <span class="keyword">from</span> emp e,dept d <span class="keyword">where</span> e.dept_id <span class="operator">=</span> d.id;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/MuqJIPXTa5sWZ1z.png" alt="008_多表查询_06.png"></p><ol start="2"><li>显式内连接</li></ol><p>语法：<code>SELECT 字段列表 FROM 表1 [ INNER ] JOIN 表2 ON 连接条件 ... ;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 显示内连接,就是通过inner join实现</span></span><br><span class="line"><span class="keyword">select</span> e.name,d.name <span class="keyword">from</span> emp e <span class="keyword">inner</span> <span class="keyword">join</span> dept d <span class="keyword">on</span> e.dept_id <span class="operator">=</span> d.id;</span><br></pre></td></tr></table></figure><p><strong>表的别名语法</strong></p><ol><li><code>tablea as 别名1 , tableb as 别名2;</code></li><li><code>tablea 别名1 , tableb 别名2; </code></li></ol><p>注意：<strong>一旦为表起了别名，就不能再使用表名来指定对应的字段</strong>了，此时只能够使用别名来指定字段。</p><h4 id="外连接">外连接</h4><p>就是两表的交集+其中一个表,比如</p><ol><li>左外连接 A+AUB</li></ol><p>语法：<code>SELECT 字段列表 FROM 表1 LEFT [ OUTER ] JOIN 表2 ON 条件 ... ;  </code> 就是关键字<strong>left join</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 左外连接-相当于表1+表1与表2的交集，右连接同理</span></span><br><span class="line"><span class="keyword">select</span> e.<span class="operator">*</span>,d.name <span class="keyword">from</span> emp e <span class="keyword">left</span> <span class="keyword">outer</span> <span class="keyword">join</span> dept d <span class="keyword">on</span> e.dept_id <span class="operator">=</span> d.id;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/AMRSQwj8co3EylU.png" alt="008_多表查询_07.png"></p><ol start="2"><li>右外连接 AUB+B</li></ol><p>语法：<code>SELECT 字段列表 FROM 表1 RIGHT [ OUTER ] JOIN 表2 ON 条件 ... ;  </code>就是关键字<strong>right join</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 右外连接</span></span><br><span class="line"><span class="keyword">select</span> d.<span class="operator">*</span>,e.<span class="operator">*</span> <span class="keyword">from</span> emp e <span class="keyword">right</span> <span class="keyword">outer</span> <span class="keyword">join</span> dept d <span class="keyword">on</span> e.dept_id <span class="operator">=</span> d.id;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/VYXqrTbgJil4Sja.png" alt="008_多表查询_08.png"></p><blockquote><p>左右外连接理论上是可以相互替换和相互转换的，不过一般左外连接用的多。</p></blockquote><h4 id="自连接">自连接</h4><p>将表自身看做是另一张表，然后将两表连接<br>语法：<code>SELECT 字段列表 FROM 表A 别名A JOIN 表A 别名B ON 条件 ... ;  </code></p><p>自连接可以是内连接也可以是外连接</p><p>示意图</p><p><img src="https://s2.loli.net/2024/11/26/VsB1neoXZOrH7iq.png" alt="008_多表查询_09.png"></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 其实就是把自己看做是两张表进行连接 不过需要取别名否则会产生歧义</span></span><br><span class="line"><span class="keyword">select</span> a.name,b.name <span class="keyword">from</span> emp a,emp b <span class="keyword">where</span> a.managerid <span class="operator">=</span> b.id;</span><br><span class="line"><span class="keyword">select</span> a.name,b.name <span class="keyword">from</span> emp a <span class="keyword">left</span> <span class="keyword">join</span> emp b <span class="keyword">on</span> a.managerid <span class="operator">=</span> b.id;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/DSmIfrxGZyH1v5e.png" alt="008_多表查询_10.png"></p><p><img src="https://s2.loli.net/2024/11/26/NpHh89GnyTPslIi.png" alt="008_多表查询_11.png"></p><blockquote><p>在自连接查询时必须取别名，否则会有歧义导致无法运行</p></blockquote><h4 id="联合查询">联合查询</h4><p>概念：就是把多次查询的结果合并起来，形成一个新的查询结果集</p><p>语法：</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> 字段列表 <span class="keyword">FROM</span> 表A ...</span><br><span class="line"><span class="keyword">UNION</span> [ <span class="keyword">ALL</span> ]</span><br><span class="line"><span class="keyword">SELECT</span> 字段列表 <span class="keyword">FROM</span> 表B ....;</span><br></pre></td></tr></table></figure><ol><li>联合的表列数和字段类型必须保持一致</li><li>用all会将所有的数据合在一起，而不用all就会<strong>去重</strong></li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 联合查询</span></span><br><span class="line"><span class="comment">-- 相当于将查询得到的两张表上下拼起来</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> salary <span class="operator">&gt;</span><span class="number">6000</span></span><br><span class="line"><span class="keyword">union</span> <span class="keyword">all</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> age <span class="operator">&lt;</span> <span class="number">50</span>;</span><br><span class="line"><span class="comment">-- 如果要去重，就不写all</span></span><br><span class="line"><span class="comment">-- 注意：查询的多张表列数要一致，字段类型要保持一致</span></span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/4fFzeprCS7JdHh1.png" alt="008_多表查询_12.png"></p><p>这里的联合查询就是将两张表上下拼接的</p><h4 id="子查询">子查询</h4><p>概念：就是sql语句中嵌套select语句，也就是将select查询出的结果作为另一个sql语句的参数</p><p>示例：<code>SELECT * FROM t1 WHERE column1 = ( SELECT column1 FROM t2 );  </code></p><ol><li>标量子查询（子查询结果为单个值）</li></ol><p>常见的操作符：<code>= &lt;&gt; &gt; &gt;= &lt; &lt;=  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 子查询-又称嵌套查询</span></span><br><span class="line"><span class="comment">-- 把表看做是矩阵，就容易理解查询的结果</span></span><br><span class="line"><span class="comment">-- 标量子查询</span></span><br><span class="line"><span class="comment">-- select id from dept where name = &#x27;研发部&#x27;查询结果只有一个，称为标量子查询</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> dept_id <span class="operator">=</span> (<span class="keyword">select</span> id <span class="keyword">from</span> dept <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;总经办&#x27;</span>);</span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> entrydate <span class="operator">&gt;</span> (<span class="keyword">select</span> entrydate <span class="keyword">from</span> emp <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;杨逍&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/sBlcqELTJZ6pKwb.png" alt="008_多表查询_13.png"></p><ol start="2"><li>列子查询(子查询结果为一列)</li></ol><p>操作符</p><table><thead><tr><th>操作符</th><th>描述</th></tr></thead><tbody><tr><td>IN</td><td>在指定的集合范围之内，多选一</td></tr><tr><td>NOT IN</td><td>不在指定的集合范围之内</td></tr><tr><td>&lt;&gt;</td><td>不等于</td></tr><tr><td>ANY</td><td>子查询返回列表中，有任意一个满足即可</td></tr><tr><td>SOME</td><td>与ANY等同，使用SOME的地方都可以使用ANY</td></tr><tr><td>ALL</td><td>子查询返回列表的所有值都必须满足</td></tr></tbody></table><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 列查询</span></span><br><span class="line"><span class="keyword">select</span> id <span class="keyword">from</span> dept <span class="keyword">where</span> name  <span class="operator">=</span> <span class="string">&#x27;销售部&#x27;</span> <span class="keyword">or</span> name <span class="operator">=</span> <span class="string">&#x27;研发部&#x27;</span>;</span><br><span class="line"><span class="keyword">select</span> salary <span class="keyword">from</span> emp <span class="keyword">where</span> dept_id <span class="operator">=</span> (<span class="keyword">select</span> id <span class="keyword">from</span> dept <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;研发部&#x27;</span>);</span><br><span class="line"><span class="comment">-- 比研发部所有人工资还要高的员工信息</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> salary <span class="operator">&gt;</span> <span class="keyword">all</span> (<span class="keyword">select</span> salary <span class="keyword">from</span> emp <span class="keyword">where</span> dept_id <span class="operator">=</span> (<span class="keyword">select</span> id <span class="keyword">from</span> dept <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;研发部&#x27;</span>));</span><br><span class="line"><span class="comment">-- 比研发部任意一个人工资高的员工信息,用any和some都行</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> salary <span class="operator">&gt;</span> <span class="keyword">any</span> (<span class="keyword">select</span> salary <span class="keyword">from</span> emp <span class="keyword">where</span> dept_id <span class="operator">=</span> (<span class="keyword">select</span> id <span class="keyword">from</span> dept <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;研发部&#x27;</span>));</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/NAmWyOZJdFK9R3I.png" alt="008_多表查询_14.png"></p><p><img src="https://s2.loli.net/2024/11/26/4tfWYH3PqxF1UQu.png" alt="008_多表查询_15.png"></p><ol start="3"><li>行子查询(子查询结果为一行)</li></ol><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 其实就是查询出来的多个字段作为另一个查询语句的条件</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> (salary,managerid) <span class="operator">=</span> (<span class="keyword">select</span> salary,managerid <span class="keyword">from</span> emp <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;韦一笑&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/VYLNzSaIAylwvkZ.png" alt="008_多表查询_16.png"></p><ol start="4"><li>表子查询(子查询结果为多行多列)</li></ol><p>关键字：<strong>in</strong></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 将查询出来的表作为范围继续查找</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> emp <span class="keyword">where</span> (job,salary) <span class="keyword">in</span> (<span class="keyword">select</span> job,salary <span class="keyword">from</span> emp <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;张无忌&#x27;</span> <span class="keyword">or</span> name <span class="operator">=</span> <span class="string">&#x27;韦一笑&#x27;</span>);</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/dYVlEfNDZ6hqtgM.png" alt="008_多表查询_17.png"></p><hr><h2 id="事务">事务</h2><p>概念：是一组操作的集合，它是一个不可分割的工作单位，事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求，即这些操作要么同时成功，要么同时失败。  常用于银行转账、贸易等。</p><p>注意：<strong>默认MySQL的事务是自动提交的</strong>，也就是说，当执行完一条DML语句时，MySQL会立即隐式的提交事务。  用git来比喻的话就是当你执行一段DML语句之后，会将数据“add”，而由于MySQL默认提交事务，“add“的同时又”commit“了。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 一组操作的集合，“同患难共享福”，</span></span><br><span class="line"><span class="comment">-- 数据准备</span></span><br><span class="line"><span class="comment">-- 数据准备</span></span><br><span class="line"><span class="keyword">create table</span> account(</span><br><span class="line">                        id <span class="type">int</span> auto_increment <span class="keyword">primary key</span> comment <span class="string">&#x27;主键ID&#x27;</span>,</span><br><span class="line">                        name <span class="type">varchar</span>(<span class="number">10</span>) comment <span class="string">&#x27;姓名&#x27;</span>,</span><br><span class="line">                        money <span class="type">int</span> comment <span class="string">&#x27;余额&#x27;</span></span><br><span class="line">) comment <span class="string">&#x27;账户表&#x27;</span>;</span><br><span class="line"><span class="keyword">insert into</span> account(id, name, money) <span class="keyword">VALUES</span> (<span class="keyword">null</span>,<span class="string">&#x27;张三&#x27;</span>,<span class="number">2000</span>),(<span class="keyword">null</span>,<span class="string">&#x27;李四&#x27;</span>,<span class="number">2000</span>);</span><br><span class="line"><span class="comment">-- 转账事务</span></span><br><span class="line"><span class="comment">-- 设置事务为自动提交 在MySQL中事务是自动提交的</span></span><br><span class="line"><span class="keyword">select</span> @<span class="variable">@autocommit</span>;</span><br><span class="line"><span class="comment">-- 设置事务为手动提交</span></span><br><span class="line"><span class="keyword">set</span> @<span class="variable">@autocommit</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"><span class="comment">-- 转账操作 (张三给李四转账1000)</span></span><br><span class="line"><span class="comment">-- 1. 查询张三账户余额</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> account <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;张三&#x27;</span>;</span><br><span class="line"><span class="comment">-- 2. 将张三账户余额-1000</span></span><br><span class="line"><span class="keyword">update</span> account <span class="keyword">set</span> money <span class="operator">=</span> money <span class="operator">-</span> <span class="number">1000</span> <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;张三&#x27;</span>;</span><br><span class="line"><span class="comment">-- 3. 将李四账户余额+1000</span></span><br><span class="line"><span class="keyword">update</span> account <span class="keyword">set</span> money <span class="operator">=</span> money <span class="operator">+</span> <span class="number">1000</span> <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;李四&#x27;</span>;</span><br><span class="line"><span class="comment">-- 提交事务</span></span><br><span class="line"><span class="comment">-- 也就是将事务放在set和commit语句之间(事务为手动提交时);</span></span><br><span class="line"><span class="keyword">commit</span>;</span><br><span class="line"><span class="comment">-- 回滚事务 </span></span><br><span class="line"><span class="keyword">rollback</span>;</span><br><span class="line"><span class="comment">-- 恢复数据</span></span><br><span class="line"><span class="keyword">update</span> account <span class="keyword">set</span> money <span class="operator">=</span> <span class="number">2000</span> <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;张三&#x27;</span> <span class="keyword">or</span> name <span class="operator">=</span> <span class="string">&#x27;李四&#x27;</span>;</span><br></pre></td></tr></table></figure><p>事务正常运行的情况</p><p><img src="https://s2.loli.net/2024/11/26/sGg6tyENAzTrVQb.png" alt="009_事务_01.png"></p><p><img src="https://s2.loli.net/2024/11/26/N79X1Z2woWJuHFh.png" alt="009_事务_02.png"></p><p>事务异常执行的情况</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 第二种创建事务的方法</span></span><br><span class="line"><span class="comment">-- 转账操作 (张三给李四转账1000)</span></span><br><span class="line"><span class="keyword">start</span> transaction ;</span><br><span class="line"><span class="comment">-- 1. 查询张三账户余额</span></span><br><span class="line"><span class="keyword">select</span> <span class="operator">*</span> <span class="keyword">from</span> account <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;张三&#x27;</span>;</span><br><span class="line"><span class="comment">-- 2. 将张三账户余额-1000</span></span><br><span class="line"><span class="keyword">update</span> account <span class="keyword">set</span> money <span class="operator">=</span> money <span class="operator">-</span> <span class="number">1000</span> <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;张三&#x27;</span>;</span><br><span class="line"></span><br><span class="line">程序执行报错 ...</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 3. 将李四账户余额+1000</span></span><br><span class="line"><span class="keyword">update</span> account <span class="keyword">set</span> money <span class="operator">=</span> money <span class="operator">+</span> <span class="number">1000</span> <span class="keyword">where</span> name <span class="operator">=</span> <span class="string">&#x27;李四&#x27;</span>;</span><br><span class="line"><span class="comment">-- 提交事务</span></span><br><span class="line"><span class="keyword">commit</span>;</span><br><span class="line"><span class="comment">-- 回滚事务</span></span><br><span class="line"><span class="keyword">rollback</span>;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/HS3K1jQyLCqbaNJ.png" alt="009_事务_03.png"></p><p><img src="https://s2.loli.net/2024/11/26/NztM1BFCqLldk32.png" alt="009_事务_04.png"></p><h4 id="控制事务">控制事务</h4><ol><li>开启事务</li></ol><p>语法：<code>START TRANSACTION 或 BEGIN ;  </code></p><ol start="2"><li>查看/设置事务的提交方式</li></ol><p>语法：<code>SELECT @@autocommit ;  </code> 自动提交，或者是<code>SET @@autocommit = 0 ;</code>手动提交</p><ol start="3"><li>提交事务</li></ol><p>语法：<code>COMIT</code> 如果是自动提交就不需要写,如果更改为手动提交，那么后面的sql语句要想修改数据必须运行此代码。</p><ol start="4"><li>回滚事务</li></ol><p>语法：<code>ROLLBACK</code>;</p><h4 id="事务的特性">事务的特性</h4><p>四大特性</p><ol><li><p>原子性（Atomicity）：事务是不可分割的最小操作单元，要么全部成功，要么全部失败。</p></li><li><p>一致性（Consistency）：事务完成时，必须使所有的数据都保持一致状态。</p></li><li><p>隔离性（Isolation）：数据库系统提供的隔离机制，保证事务在不受外部并发操作影响的独立环境下运行。</p></li><li><p>持久性（Durability）：事务一旦提交或回滚，它对数据库中的数据的改变就是永久的。</p></li></ol><p>上述就是事务的四大特性，简称<strong>ACID</strong>。</p><h4 id="并发事务问题">并发事务问题</h4><p>补充示意图</p><ol><li>脏读：一个事务读到另外一个事务还没有提交的数据</li><li>不可重复读：一个事务先后读取同一条记录，但两次读取的数据不同，称之为不可重复读</li><li>幻读：一个事务按照条件查询数据时，没有对应的数据行，但是在插入数据时，又发现这行数据已经存在，好像出现了 “幻影”。</li></ol><h4 id="事务隔离级别">事务隔离级别</h4><table><thead><tr><th>隔离级别</th><th>脏读</th><th>不可重复读</th><th>幻读</th></tr></thead><tbody><tr><td>Read uncommitted</td><td>√</td><td>√</td><td>√</td></tr><tr><td>Read committed</td><td>×</td><td>√</td><td>√</td></tr><tr><td>Repeatable Read(默认)</td><td>×</td><td>×</td><td>√</td></tr><tr><td>Serializable</td><td>×</td><td>×</td><td>×</td></tr></tbody></table><ol><li>查看事务隔离级别</li></ol><p>语法：<code>SELECT @@TRANSACTION_ISOLATION;  </code></p><p><img src="https://s2.loli.net/2024/11/26/AYSl1biIwhNH5Xy.png" alt="009_事务_05.png"></p><ol start="2"><li>设置事务隔离级别</li></ol><p>语法：<code>SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL &#123; READ UNCOMMITTED |READ COMMITTED | REPEATABLE READ | SERIALIZABLE &#125;  </code></p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 设置事务隔离级别</span></span><br><span class="line"><span class="keyword">set</span> session transaction isolation level read uncommitted;</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/D4Jdx58CovbzAM6.png" alt="009_事务_06.png"></p><blockquote><p>事务隔离级别越高，数据越安全，但是性能越低。</p></blockquote><p><strong>至此基础篇完结</strong></p><p>学习完之后可以参考此进阶篇学习</p><ol class="series-items"><li><a href="/posts/mysql-series-one/" title="MySQL学习笔记(一)基础篇">MySQL学习笔记(一)基础篇</a></li><li><a href="/posts/mysql-series-two/" title="MySQL学习笔记(二)进阶篇">MySQL学习笔记(二)进阶篇</a></li><li><a href="/posts/database-principle/" title="MySQL学习笔记(零)数据库原理">MySQL学习笔记(零)数据库原理</a></li></ol><h1>参考</h1><p><strong>视频教程</strong></p><ol><li><a href="https://www.bilibili.com/video/BV1Kr4y1i7ru?p=2&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">黑马程序员</a></li><li><a href="https://www.bilibili.com/video/BV1iq4y1u7vj?vd_source=bb8dacb993f11c0e39f8147c98a2894c">尚硅谷</a></li></ol><p><strong>笔记参考</strong></p><ol><li>在浏览器上搜索“黑马程序员”进入官网，然后点击免费教程-“搜索mysql”，下载对应文件</li><li><a href="https://jimhackking.github.io/%E8%BF%90%E7%BB%B4/MySQL%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/#more">MySQL学习笔记 | 智云知识</a></li></ol>]]></content>
    
    
    <summary type="html">教你学会MySQL的基础知识，为测试、运维、后端开发、索引优化等方面做准备</summary>
    
    
    
    <category term="MySQL" scheme="https://lloydkai.cn/categories/MySQL/"/>
    
    
    <category term="MySQL" scheme="https://lloydkai.cn/tags/MySQL/"/>
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>hexo博客系列(三)博客写作指南</title>
    <link href="https://lloydkai.cn/posts/blog-series-three/"/>
    <id>https://lloydkai.cn/posts/blog-series-three/</id>
    <published>2024-10-26T14:04:54.000Z</published>
    <updated>2026-04-23T01:46:59.833Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/XLE3qtOQlyifzHC.jpg" alt></p><h1>简介</h1><p>在撰写博客的过程中，内容至关重要但不是唯一重要的因素，排版、图片、交互体验等视觉设计也同样需要关注。一个设计精美、易于阅读的博客会吸引更多读者，提升用户体验。本文将为你提供一套完整的 markdown 博客创作指南，从实战的角度帮助你写出既有深度又美观的博客文章。</p><h1>准备工具</h1><h2 id="写作工具">写作工具</h2><p>个人比较推崇<strong>Typora</strong>这种简洁的支持<strong>markdown</strong>格式的编辑器，相比之下，obsidian的布局不利于专注于写作，notion的自定义布局和数据库这两大突出优势在markdown格式下会有损失，vscode依赖于插件。</p><p>总之就是一句话:</p><blockquote><p>能让你心无旁骛地去写的编辑器就是最好的</p></blockquote><h2 id="博客引擎">博客引擎</h2><p>本文基于hexo+butterfly的主题进行博客创作，但读者无须担心，博客创作更多的在于<strong>文章结构</strong>、<strong>词句修辞</strong>、<strong>排版和可读性</strong>方面下功夫，其他方面依赖博客引擎和前端特性的并不多，读者可以在CSDN、博客园、掘金社区等其他地方同样可以撰写和托管博客。</p><h1>博客撰写讲解</h1><h2 id="目录结构">目录结构</h2><p>好的目录结构要梳理文章逻辑，如果是<strong>新闻热点点评类</strong>，就要能讲清楚事件发生的时间地点人物，发生原因及其分析，结论、启示或者经验教训；如果是<strong>技术分享类</strong>，就要说明技术的应用范围，原理，怎样配置技术所需的环境，阐明使用技术的效果等。这方面主要靠读者多看技术大佬的博客、优秀的公众号推文等，看他们的目录是如何区分的，只要能达到<strong>行云流水</strong>的效果就行，不需要在分级、格式方面过于讲究。</p><p>可供参考的文章结构：大部分都是<strong>总-分-总</strong>结构</p><ul><li>提出问题-&gt;分析问题-&gt;解决问题-&gt;总结经验，技术问题分享。</li><li>背景-&gt;思考-&gt;尝试-&gt;遇到的困难-&gt;解决方案-&gt;最后结果，问题分享</li><li>摘要-&gt;简介-&gt;分支主题-&gt;总结，一般技术分享。</li><li>是什么-原理-背景&gt;解决了什么问题-&gt;基本操作-&gt;同类对比-&gt;总结 ，适合新技术分享</li></ul><p>参考的目录结构如下，以markdown格式的代码块展示,这里<code>//</code>及其后面的内容代表注释</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 简介    </span></span><br><span class="line"><span class="section"># 一、准备工作 //一些环境配置，安装等，或者是解决问题的背景等</span></span><br><span class="line"><span class="section">## 1.centos安装  //以数字的形式合理分级，建议标题的层级不要超过四层</span></span><br><span class="line"><span class="section">## 2.idea解包</span></span><br><span class="line"><span class="section">## ……</span></span><br><span class="line"><span class="section"># 二、基本用法 //对于技术文章就像是语法书，对于问题就是发现问题，分析问题，</span></span><br><span class="line"><span class="section">## 1. 对页面的操作</span></span><br><span class="line"><span class="section">## 2. 1 初始化浏览器对象</span></span><br><span class="line"><span class="section">## 2. 2</span></span><br><span class="line"><span class="section">## ……</span></span><br><span class="line"><span class="section"># 三、高阶用法  //或者是多个解决方案</span></span><br><span class="line"><span class="section"># 总结  //对技术或者过程的总结，建议不要太长</span></span><br><span class="line"><span class="section"># 参考  //把你写作过程中参考的资料，或者是推荐的链接放在这里，便于读者后续学习</span></span><br><span class="line"><span class="section"># 开源协议  //如果使用的是hexo或者其他博客网站，撰写博客的时候会自动生成，不需要自己写</span></span><br></pre></td></tr></table></figure><h3 id="标题">标题</h3><p>取标题要注意几点</p><ol><li><strong>简洁直观</strong>：不仅仅是利于搜索引擎优化，更多的是便于读者和自己，读者可以通过标题判断博客的信息对于自己是否有效，作者可以根据标题了解自己博客的侧重方面。<strong>不要被国内电商式的标题所蒙蔽</strong>(比如“爆肝……”“震惊，百大up主齐聚一堂竟然是为……”)，虽然能带来流量，但是作者不太建议，这种标题就显得作者没有真才实学，只能靠眼球吸引读者，</li><li><strong>关键词</strong>：标题一定要包含文章的高频词或者是重点词语，比如如果你写的是有关MySQL的学习知识分享，那么关键字就是“MySQL”，可能有“教程”等其他关键词，再用适当的句子结构(问句、陈述句等)将其组合为标题。比如组合为”MySQL学习指南(一)“</li></ol><p><strong>特殊</strong>:所有<strong>系列文章</strong>(比如MySQL学习笔记)的标题要一致，<strong>相关的</strong>可以不一致。标题+XX:XX为数字，不满两位用0替代;比如mysql01;标题+(序数词):比如mysql学习(一)</p><h3 id="简介">简介</h3><p>文章的标题和简要介绍一下文章，要解决的是什么问题</p><p><strong>示例</strong>：Selenium是广泛使用的模拟浏览器运行的库，它是一个用于Web应用程序测试的工具。 Selenium测试直接运行在浏览器中，就像真正的用户在操作一样，并且支持大多数现代 Web 浏览器。下面就进入正式的学习阶段。</p><h3 id="文章主体">文章主体</h3><p>以下主要侧重于排版。</p><ol><li>段落：建议不要太长，最好保持在300字以内</li><li>字体效果：用黑体强调重要词汇，用斜体或者下划线强调重要段落</li><li>列表：恰当使用无序和有序列表，对于超过10个点的列表建议使用markdown里面的表格</li><li>图片：如果图片能便于读者理解，减少文字量，可以使用。</li><li>代码块：建议默认收起或者收缩，需要的时候读者点击即可全部展开。指明代码块对应的编程语言，不是的话要提前说明</li><li>分割线：建议用在两个一级标题或者是两段长段落之间。</li></ol><p>注意事项</p><ol><li>所有的代码至少要在自己的电脑上或者对应的运行环境上运行，否则不写</li><li>不易理解或者抽象的地方要用图解释，可以是GIF动图制作也可以是chartjs、echart等，注意不要泄漏私人信息。</li><li>模棱两可或者自己不懂的不要轻易写，写的话注意叠甲。</li></ol><h2 id="超文本内容">超文本内容</h2><p>这一部分主要涉及前端的特性，属于是锦上添花的内容，即使没有也不是特别影响文章的质量，就算《资本论》只有文字，也无可争议是最伟大的鸿篇巨著之一。</p><p>常用的类型有：图片、动画(gif等)、视频、音频、表情、标签外挂、图标、链接等。</p><h3 id="图表">图表</h3><ol><li><a href="https://excalidraw.com/">Excalidraw</a>：手绘风格的开源工具，适合绘制思维导图、流程图等。</li></ol><p><img src="https://s2.loli.net/2024/11/26/lvhXLijoyQYUnkb.png" alt="博客写作指南_01"></p><ol start="2"><li><a href="https://mermaid.nodejs.cn/">Mermaid 中文网</a>：基于 Markdown 的流程图工具，可以生成流程图、时序图等。或者也可以使用<a href="https://app.diagrams.net/">draw.io</a>。主要侧重于计算机方面的知识图表，常用于UML统一建模语言。</li></ol><div class="mermaid-wrap"><pre class="mermaid-src" hidden>    sequenceDiagram    participant Alice    participant Bob    Alice-&gt;&gt;John: Hello John, how are you?    loop HealthCheck        John-&gt;&gt;John: Fight against hypochondria    end    Note right of John: Rational thoughts &lt;br&#x2F;&gt;prevail!    John--&gt;&gt;Alice: Great!    John-&gt;&gt;Bob: How about you?    Bob--&gt;&gt;John: Jolly good!  </pre></div><ol start="3"><li><a href="https://chartjs.cn/docs/latest/">Chart.js 中文网</a>：是一个用于创建动态图表的 JavaScript 库，适合做一些比较复杂的数据分析图。</li></ol><div class="chartjs-container chartjs-abreast" data-chartjs-id data-width="40%">            <pre class="chartjs-src" hidden>{    &quot;type&quot;: &quot;pie&quot;,    &quot;data&quot;: {        &quot;labels&quot;: [            &quot;编程&quot;,            &quot;音乐&quot;,            &quot;阅读&quot;,            &quot;游戏&quot;,            &quot;健身&quot;,            &quot;旅游&quot;        ],        &quot;datasets&quot;: [            {                &quot;label&quot;: &quot;喜爱指数&quot;,                &quot;data&quot;: [                    30,                    24,                    19,                    14,                    9,                    4                ],                &quot;backgroundColor&quot;: {                    &quot;dark-mode&quot;: [                        &quot;rgba(255, 99, 132, 0.5)&quot;,                        &quot;rgba(54, 162, 235, 0.5)&quot;,                        &quot;rgba(255, 206, 86, 0.5)&quot;,                        &quot;rgba(75, 192, 192, 0.5)&quot;,                        &quot;rgba(153, 102, 255, 0.5)&quot;,                        &quot;rgba(255, 159, 64, 0.5)&quot;                    ],                    &quot;light-mode&quot;: [                        &quot;rgba(255, 99, 132, 0.2)&quot;,                        &quot;rgba(54, 162, 235, 0.2)&quot;,                        &quot;rgba(255, 206, 86, 0.2)&quot;,                        &quot;rgba(75, 192, 192, 0.2)&quot;,                        &quot;rgba(153, 102, 255, 0.2)&quot;,                        &quot;rgba(255, 159, 64, 0.2)&quot;                    ]                },                &quot;borderColor&quot;: {                    &quot;dark-mode&quot;: [                        &quot;rgba(255, 99, 132, 1)&quot;,                        &quot;rgba(54, 162, 235, 1)&quot;,                        &quot;rgba(255, 206, 86, 1)&quot;,                        &quot;rgba(75, 192, 192, 1)&quot;,                        &quot;rgba(153, 102, 255, 1)&quot;,                        &quot;rgba(255, 159, 64, 1)&quot;                    ],                    &quot;light-mode&quot;: [                        &quot;rgba(255, 99, 132, 1)&quot;,                        &quot;rgba(54, 162, 235, 1)&quot;,                        &quot;rgba(255, 206, 86, 1)&quot;,                        &quot;rgba(75, 192, 192, 1)&quot;,                        &quot;rgba(153, 102, 255, 1)&quot;,                        &quot;rgba(255, 159, 64, 1)&quot;                    ]                }            }        ]    },    &quot;options&quot;: {        &quot;plugins&quot;: {            &quot;legend&quot;: {                &quot;labels&quot;: {                    &quot;color&quot;: {                        &quot;dark-mode&quot;: &quot;rgba(255, 255, 255, 0.8)&quot;,                        &quot;light-mode&quot;: &quot;rgba(0, 0, 0, 0.8)&quot;                    }                }            }        }    }}</pre>            <div class="chartjs-desc"><p>除了<strong>计算机编程</strong>外，我想不出还有其他让我感兴趣的工作。<br>我可以无中生有地创造出<strong>精美的范式</strong>和<strong>结构</strong>，<br>在此过程中也解决了无数的小谜团。<br><span style="font-size:0.8em;color: var(--sep-secondtext);">I can’t think of any other job other than <strong>computer programming</strong> that interests me.<br>I can create <strong>beautiful paradigms</strong> and <strong>structures</strong> out of nothing,<br>Countless small mysteries are also solved in the process.</span></p></div>          </div><h3 id="视频">视频</h3><ol><li>B站引用：打开网页版的bilibili，点击要分享的视频-“分享”-“嵌入代码”，然后粘贴到markdown文件内即可。参考如下</li></ol><div style="position: relative; width: 100%; height: 0; padding-bottom: 75%;">    <iframe src="//player.bilibili.com/player.html?isOutside=true&aid=552211531&bvid=BV1vi4y1C73C&cid=547518386&p=1&autoplay=0" scrolling="no" border="0" frameborder="no" framespacing="0" high_quality="1" allowfullscreen="true" style="position:absolute; height: 100%; width: 100%;">    </iframe></div><h3 id="公式">公式</h3><p>建议使用katex，或者是markdown本地的公式嵌入。</p><p>参考教程<a href="https://freeopen.github.io/mathjax/">Markdown 数学公式指导手册 | Freeopen</a></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msup><mrow><mi>sin</mi><mo>⁡</mo></mrow><mn>2</mn></msup><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>+</mo><msup><mrow><mi>cos</mi><mo>⁡</mo></mrow><mn>2</mn></msup><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">\sin^2(\theta) + \cos^2(\theta) = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1219em;vertical-align:-0.25em;"></span><span class="mop"><span class="mop">sin</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8719em;"><span style="top:-3.1208em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mop"><span class="mop">cos</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></p><h3 id="表情符号">表情符号</h3><ol><li><a href="https://www.lddgo.net/common/emoticons">在线颜文字大全</a> ：与markdown兼容，基本不会有不显示等问题</li><li><a href="https://www.emojiall.com/zh-hans/categories/A">表情包</a> ：注意typora的表情(格式为<code>:表情</code>)无法直接在hexo显示，需要用插件和配置解决(已经解决)</li><li><a href="https://fontawesome.com/v4/icons/">图标</a>：适当的图标可以让人记忆犹新，见图思义。</li></ol><h3 id="交互式的组件">交互式的组件</h3><p>比如butterfly中的button、图床等，由于不同的博客引擎涉及的组件不同，这里就不展开。建议读者不要舍本逐末，过度美化而忽视文章的内容。</p><h2 id="总结与参考">总结与参考</h2><ul><li><p>用一段话给文章内容作总结。</p></li><li><p><strong>参考</strong>要注明来源，比如链接、转载出处，注意定期更新以防失效。</p></li></ul><h1>参考</h1><ol><li><a href="https://www.cnblogs.com/returntmp/p/17591866.html">【全方位解析】如何写好技术文章 - ReturnTmp - 博客园</a></li></ol>]]></content>
    
    
    <summary type="html">本文将从实战的角度出发，提供一套完整的 markdown 博客创作指南，帮助读者写出既有深度又美观的博客文章。</summary>
    
    
    
    <category term="blog" scheme="https://lloydkai.cn/categories/blog/"/>
    
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="blog" scheme="https://lloydkai.cn/tags/blog/"/>
    
  </entry>
  
  <entry>
    <title>Linux学习笔记(一)Centos</title>
    <link href="https://lloydkai.cn/posts/Linux-series-one/"/>
    <id>https://lloydkai.cn/posts/Linux-series-one/</id>
    <published>2024-10-22T11:20:06.000Z</published>
    <updated>2026-04-23T01:47:53.965Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/KuYxMTlRckENvI5.jpg" alt></p><blockquote><p>本博客使用的是Centos7版本</p></blockquote><h1>学前提醒</h1><ol><li>不要死记Linux命令，先敲一遍，以后在学习和工作中练习就足够了，需要的时候就查命令手册</li><li>Centos在2024年已停止维护，这篇博客<strong>主要介绍Centos的基础命令(Linux发行版基础指令基本一样)，不涉及其进阶操作</strong>。建议读者可以学一下ubuntu、Debian等其他常用的Linux发行版</li></ol><h1>初识Linux</h1><ol><li><p>什么是Linux？即<strong>服务器操作系统</strong>的一种。<strong>操作系统就是第一层软件</strong>，作为用户和计算机硬件之间的桥梁，调度和管理计算机硬件进行工作。Linux是前后端开发人员、运维测试人员、大数据分析人员等必学的内容。</p></li><li><p>Linux的组成：由Linux系统<strong>内核</strong>+系统级应用<strong>程序</strong>(简单理解成系统自带的软件，比如文件管理，图片查看等)组成，其他的软件都叫第三方应用程序。这其中<strong>最重要的就是内核</strong>。读者可以点开此链接<a href="https://www.kernel.org">Linux内核官网</a> 下载其内核源码。</p></li></ol><p><img src="https://s2.loli.net/2024/11/26/ZyNvmFsY7xHLaoR.png" alt="Linux系统组成示意图.png"></p><p><img src="https://s2.loli.net/2024/11/26/h1jPXA5fC9cpUxS.png" alt="Linux调度流程图.png"></p><ol start="3"><li>Linux发行版：任何人都可以获得并修改内核，并且自行集成系统级程序，提供了内核+系统级程序的完整封装，称之为Linux发行版。常见的ubuntu和redhat等就是Linux的发行版。所以也<strong>不要纠结学哪一个，学会了一个，其他的都会触类旁通了</strong>。</li></ol><h2 id="虚拟机">虚拟机</h2><p>虚拟机就是借助虚拟化技术，我们可以在系统中，通过软件模拟计算机硬件，并给虚拟硬件安装真实的操作系统。</p><p>学习Linux可以选择使用虚拟软件，比如VMware WorkStation，或者是买一个云服务器。</p><p><strong>Windows网络连接(网络适配器)查看方法</strong>：<code>win+R</code> 输入<code>ncpa.cpl</code> 查看是否有VMnet1和VMnet8的网卡，有了虚拟机才能连上网。</p><h2 id="扩展：WSL">扩展：WSL</h2><p>就是Windows Subsystem for Linux，没错，Windows系统可以得到Linux系统环境，不过目前的主流还是用虚拟软件。</p><p>方法：(Windows 11)在开始中搜索-“启用或者关闭Windows功能”-“适用于Linux的Windows子系统 ”打勾，“虚拟机平台”打勾并重启，然后在应用商店里面搜索对应的Linux发行版下载即可。</p><h2 id="Linux的安装、配置和远程连接">Linux的安装、配置和远程连接</h2><ol><li>虚拟机软件安装：由于vmware被收购，<strong>对于个人用户完全免费</strong>，可以去官网上下载，参考教程<a href="https://b23.tv/b5GG1hz">一步步教你掌握VMware Workstation 17 Pro，成为虚拟化专家！-哔哩哔哩</a></li></ol><p><img src="https://s2.loli.net/2024/11/26/y39hfCNBVGPwodW.png" alt="001_Linux安装_01.png"></p><ol start="2"><li>查看主机的网络适配器是否正常配置：按<strong>win + r</strong>  <strong>输入ncpa.cpl回车</strong>  确保里面有VMnet1和VMnet8</li></ol><p><img src="https://s2.loli.net/2024/11/26/4OGLCP67h5WRuQs.png" alt="001_Linux安装_02.png"></p><ol start="3"><li>在VMware中安装Centos系统</li></ol><p>考虑到国内访问Centos安装包源比较困难，这里使用清华的镜像源网站，且本次使用的是Centos7.6版本，读者需要安装其他版本的都可以在<a href="https://mirrors.tuna.tsinghua.edu.cn/">清华大学镜像源网站</a>下面找。Centos下载链接：<a href="https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.6.1810/isos/x86_64/">清华大学开源软件镜像站</a></p><p><img src="https://s2.loli.net/2024/11/26/6TXloshZaMxe5Gb.png" alt="001_Linux安装_03.png"></p><p>下载好之后打开VMWare软件，点击左上角“文件”-“新建虚拟机”</p><p><img src="https://s2.loli.net/2024/11/26/TmFgOfBbyhpk5P1.png" alt="001_Linux安装_04.png"></p><p>选择“典型(推荐)”</p><p><img src="https://s2.loli.net/2024/11/26/iEqDytlGTUA1BoI.png" alt="001_Linux安装_05.png"></p><p>选择你下载的ISO文件的路径</p><p><img src="https://s2.loli.net/2024/11/26/yCS4VLrOlkcPxa1.png" alt="001_Linux安装_06.png"></p><p>设置用户名和密码</p><p><img src="https://s2.loli.net/2024/11/26/LrSInCBaeGyHmvR.png" alt="001_Linux安装_07.png"></p><p>设置虚拟机的位置</p><p><img src="https://s2.loli.net/2024/11/26/OFYfL1lHurxycpz.png" alt="001_Linux安装_08.png"></p><p>设置虚拟机的磁盘容量(图中内存是错的，改为外存)</p><p><img src="https://s2.loli.net/2024/11/26/dBoiQmA3gYUs2JC.png" alt="001_Linux安装_09.png"></p><p>自定义硬件 建议内核和内存不要分配太多</p><p><img src="https://s2.loli.net/2024/11/26/VMF36DuoO5PHf7S.png" alt="001_Linux安装_10.png"></p><p><img src="https://s2.loli.net/2024/11/26/QFCR4KW9qiuV3Ih.png" alt="001_Linux安装_11.png"></p><p><img src="https://s2.loli.net/2024/11/26/c4TzakLQJfmyeBr.png" alt="001_Linux安装_12.png"></p><p>后面就是自动安装了，大概需要10-20分钟左右。<strong>注意不要反复点击界面，否则可能会卡死需要重新安装</strong>。</p><ol start="4"><li>登录虚拟机</li></ol><p>用你之前设置的用户登录虚拟机</p><p><img src="https://s2.loli.net/2024/11/26/HfvspbVyZ7Q19Ez.png" alt="001_Linux安装_13.png"></p><p>出现“Getting Started”界面，直接退出即可。出现此界面说明你已经安装好Centos了\(^o^)/~ ,不过<strong>这可不是结束的开始，而是开始的结束</strong>。</p><p><img src="https://s2.loli.net/2024/11/26/cCdubh7JPglyKnX.png" alt="001_Linux安装_14.png"></p><ol start="5"><li>远程登录虚拟机</li></ol><p>Linux上面有图形化界面(在界面中右键-“open terminal”，但是<strong>不推荐</strong>。在开发中使用命令行的效率比图形化界面更好.<br>但是VMware中的Linux命令行页面不方便，建议使用第三方软件远程连接到Linux上(<strong>生产环境中也是远程开发</strong>)，推荐软件有Xshell和finalshell。我这里使用Xshell，finalshell同理</p><p><a href="https://www.xshell.com/zh/xshell-download/">Xshell 下载官网</a> 建议使用“家庭和学校用户的免费许可证”下的“免费授权界面”下载Xshell和XFTP(用于传输文件),我这里下载的是7版本</p><p>打开Xshell后点击右上角的“文件”-“新建”。</p><p><img src="https://s2.loli.net/2024/11/26/OBJCuNZrl1AnjmL.png" alt="001_Linux安装_15.png"></p><p>此界面重要的<strong>填写主机IP</strong>。在Centos界面中右键-“open terminal” ，命令行输入<code>ifconfig</code> 回车</p><p>图中方框部分就是此虚拟机的IP，</p><p><img src="https://s2.loli.net/2024/11/26/SPk6sbQqvRAj3Bg.png" alt="001_Linux安装_16.png"></p><p>按照你自己查找的IP将其填写在主机(H)的框中即可。</p><p><img src="https://s2.loli.net/2024/11/26/cNIZh7Uq1XtKCMo.png" alt="001_Linux安装_17.png"></p><p>会弹出如下的警告界面，点击“接收并保存”</p><p><img src="https://s2.loli.net/2024/11/26/7WZFS6UeL9Aofwx.png" alt="001_Linux安装_18.png"></p><p>选择你登录的用户名，建议<strong>使用一般用户而不是root用户</strong>。我这里演示用就用root用户了。出现如下图表示登录成功</p><p><img src="https://s2.loli.net/2024/11/26/jNres98YMiIEfDO.png" alt="001_Linux安装_19.png"></p><p><img src="https://s2.loli.net/2024/11/26/z16c7ZqIaLJBS5t.png" alt="001_Linux安装_20.png"></p><p>但是：Linux虚拟机如果重启，有可能发生IP改变，如果IP改变需要在XShell中修改连接的IP地址。以下讲解如何固定IP地址不变。</p><h2 id="Linux固定IP">Linux固定IP</h2><blockquote><p>可以在安装Centos的时候配置网络，参考链接如下<a href="https://b11et3un53m.feishu.cn/wiki/FJAnwOhpIihMkLkOKQocdWZ7nUc">day02-Docker - 飞书云文档</a></p></blockquote><p>在VMware软件中左上角点击“编辑”-“虚拟网络编辑器”，再点击“更改设置”，点击vmnet8并点击NAT设置</p><p><img src="https://s2.loli.net/2024/11/26/el6NtSZiP5ys3pE.png" alt="001_Linux安装_21.png"></p><p>按照子网设置网关IP，比如子网IP是192.188.190.0。<a href="http://xn--IP192-fq1h9c273ah50abj4fijah81khkn.188.190.xxx">那么网关IP就设置为192.188.190.xxx</a>。其中xxx在0-255之间，这里建议就用2代替xxx，IP</p><p>记住以上红色方框中的内容</p><p>然后用Xshell远程登录(使用root用户登录)，在命令行输入<code>vim /etc/sysconfig/network-scripts/ifcfg-ens33</code></p><p>然后按<code>i</code>键后输入以下内容，根据自己的实际情况改。那个``IPADDR=“建议设置成你之前ifconfig查询的IP”`</p><p><img src="https://s2.loli.net/2024/11/26/96YVtLEy3BJ7CZS.png" alt="Linux配置IP.png"></p><p>再点击esc键，输入<code>:wq</code> 回车就保存并退出了</p><p>在命令行中输入并执行<code>systemctl restart network</code> 重启网卡，执行<code>ifconfig</code>即可看到ip地址固定为你设置的IP了。</p><h2 id="扩展：用vscode远程登录Linux">扩展：用vscode远程登录Linux</h2><blockquote><p>如果涉及到Linux编程而又不想只用vim，可以考虑使用vscode</p></blockquote><ol><li>下载vscode和插件 <a href="https://code.visualstudio.com/">Visual Studio Code - Code Editing. Redefined</a></li></ol><p>然后按照图<strong>下载对应的插件</strong></p><p><img src="https://s2.loli.net/2024/11/26/E2gbTXPevDldcoM.png" alt="001_Linux安装_22.png"></p><p>安装好之后点击左下角矩形中的按钮，开启远程登录</p><p><img src="https://s2.loli.net/2024/11/26/luqcYS48wKR1Paf.png" alt="001_Linux安装_23.png"></p><p>点击“<strong>连接到主机</strong>”</p><p><img src="https://s2.loli.net/2024/11/26/Xnh7a4ZG3WwfEdC.png" alt="001_Linux安装_24.png"></p><p>这里点击“<strong>配置SSH主机</strong>”</p><p><img src="https://s2.loli.net/2024/11/26/hDmQWzekx8bS3oM.png" alt="001_Linux安装_25.png"></p><p>点击<strong>路径最后为\config</strong>的</p><p><img src="https://s2.loli.net/2024/11/26/jgxftQ4cKeWSVwb.png" alt="001_Linux安装_26.png"></p><p>注意如果你是第一次使用vscode 大概率是空的 按照以下格式填写</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Host 你的LinuxIP</span><br><span class="line">HostName 你的LinuxIP</span><br><span class="line">User 选择一个登录用户，比如root</span><br></pre></td></tr></table></figure><p>示例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Host 200.200.200.200</span><br><span class="line">HostName 200.200.200.200</span><br><span class="line">User root</span><br></pre></td></tr></table></figure><p>配置完后再次远程登录，点击你所设置的IP(见图<code>001_Linux安装_25</code>）</p><p>这样就远程登录成功了(＾－＾)V。</p><p>如果你想要<strong>打开某一文件夹</strong>进行编程，按照图片先点击”<strong>打开文件夹</strong>“然后选择即可。</p><p><img src="https://s2.loli.net/2024/11/26/Pp2tiQrnINgvuTo.png" alt="001_Linux安装_27.png"></p><h2 id="扩展：虚拟机快照">扩展：虚拟机快照</h2><p>在学习阶段我们无法避免的可能损坏Linux操作系统。如果损坏的话，重新安装一个Linux操作系统就会十分麻烦。，而vmware支持给Linux制作快照，简单来说就是“<strong>存档</strong>”，万一损坏了可以“<strong>回档</strong>”。</p><p>留下快照:右键虚拟机-点击“快照”-点击”拍摄快照“</p><p><img src="https://s2.loli.net/2024/11/26/ZSQfcM7jOy6BPKh.png" alt="001_Linux安装_28.png"></p><p>恢复快照：同样右键-快照-快照管理器，点击对应的快照并点击“转到”即可。</p><blockquote><p>小提醒：建议在关机之后留下快照，开机情况下会比较卡</p></blockquote><hr><blockquote><p>此LloydEduCentos仅作演示安装用，后续Linux学习使用的是hspEdu01的虚拟机，读者无需担心，不影响后续学习Linux</p></blockquote><h1>Linux基础</h1><p>学习Linux需要掌握<strong>命令</strong>来操作系统，图形化页面很少使用。图形化界面易于理解，但是命令行效率更高。</p><p>那么在哪里敲命令行呢？VMware里面可以，但是不方便。建议使用Xshell或者是FinalShell软件，这里我用的是Xshell。</p><h2 id="Linux目录结构">Linux目录结构</h2><p><strong>一切皆文件</strong>：指的是Linux会将一切对象映射成文件。Linux中最重要的就是目录，它不像Windows有CDE盘，只有一个根目录。<strong>在生产环境中是很少使用图形化界面的，基本只用控制台</strong>。对于其他目录要了解其英文单词和实际用途。</p><p>图片演示</p><p><img src="https://s2.loli.net/2024/11/26/FG2yNA4tCa5vLZb.png" alt="002_Linux目录结构_01.png"></p><ul><li><code>/</code>，根目录是最顶级的目录了，也就是说<code>~</code>是<code>/</code>的子目录</li><li>Linux有且只有一个顶级目录：<code>/</code></li><li>路径描述的层次关系同样适用<code>/</code>来表示:比如/usr/bin/hello.py,第一个<code>/</code>是<strong>根目录</strong>，其他的是<strong>层级关系</strong>。</li></ul><blockquote><p>注意，Linux中所有的用户在登录的时候左侧显示的都是<code>~</code> ,也就是自己的“根目录”，但其实是<code>/</code> 的子目录，<strong>其本质是/home/用户名或者是/root</strong></p></blockquote><h2 id="Linux基础命令">Linux基础命令</h2><blockquote><p>最重要的部分，学Linux就是学习使用命令与计算机交互</p></blockquote><p><strong>命令</strong>：就是Linux程序，以字符的方式与计算机交流。💡其<strong>本质</strong>上都是<strong>可执行的二进制文件</strong>。</p><p>无论是什么命令，用于什么用途，在Linux中，命令有其<strong>通用的格式</strong><br><code>command \[-options] [parameter]</code></p><ul><li>command:命令本身,比如touch\cat等</li><li>-options:[可选，非必填]命令的一些<strong>选项</strong>，可以通过选项控制命令的行为细节,比如rm -rf 其中-r -f为选项</li><li>parameter:[可选，非必填]命令的参数，多数用于命令的指向目标等. 语法中的[],表示可选的意思，比如touch file01.txt 后面的<code>file01.txt</code>就是命令的参数</li></ul><p>示例：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -l /home/hello</span><br></pre></td></tr></table></figure><p>ls是命令，-l是选项，/home/hello是参数，意思是以列表的形式，展示/home/hello 目录的内容。</p><h2 id="目录切换命令">目录切换命令</h2><h3 id="概念阐述：路径">概念阐述：路径</h3><p><strong>相对路径与绝对路径</strong></p><ul><li><p>相对路径，<strong>非</strong><code>/</code>开头的称之为相对路径：相对路径表示以<code>当前目录</code>作为起点，去描述路径，如<code>test/a.txt</code>，表示当前工作目录内的test文件夹内的a.txt文件</p></li><li><p>绝对路径，<strong>以</strong><code>/</code>开头的称之为绝对路径：绝对路径从<code>根</code>开始描述路径，比如<code>/home/jerry/download/test.txt</code> 指的就是jerry用户名下download文件内的test.txt文件。</p></li></ul><p><strong>特殊路径符</strong></p><ul><li><code>.</code>，表示当前，比如./a.txt，表示当前文件夹内的<code>a.txt</code>文件</li><li><code>..</code>，表示上级目录，比如<code>../</code>表示上级目录，<code>../../</code>表示上级的上级目录</li><li><code>~</code>，表示用户的HOME目录，比如<code>cd ~</code>，即可切回用户HOME目录</li></ul><h3 id="ls命令">ls命令</h3><p>功能：列出文件夹信息</p><p>语法：<code>ls [-l -h -a] [Linux路径]</code></p><ul><li>Linux路径：被查看的文件夹的路径，<strong>可以是绝对路径也可以是相对路径</strong>。不提供参数表示查看当前工作目录</li><li>-l，以列表(list)形式查看</li><li>-h，<strong>必须配合-l使用</strong>(否则不展示文件大小)，以更加人性化的方式显示文件大小</li><li>-a，表示all的意思，即显示所有文件，<strong>包括隐藏文件</strong>(在Linux中以<code>.</code>开头的，均是隐藏的)</li></ul><p>用的最多的一般是<code>ls</code>与<code>ls -lh</code></p><p>演示如下</p><p><img src="https://s2.loli.net/2024/11/26/J7ckzjlp3CeAaFv.png" alt="002_目录切换命令_01.png"></p><p>语法中的选项是可以组合使用的，比如学习的-和-l可以组合应用,比如<code>ls -la</code></p><p><img src="https://s2.loli.net/2024/11/26/BsDfNTpLqO5CzP9.png" alt="002_目录切换命令_02.png"></p><p>绝对路径和相对路径作为参数，效果相同|这里演示-h不配合-l使用的效果</p><p><img src="https://s2.loli.net/2024/11/26/Knm1CiuPWSXY6BD.png" alt="002_目录切换命令_03.png"></p><h3 id="cd命令">cd命令</h3><p>change directory</p><p><strong>注意</strong>：Linux登录的时候会将当前<strong>登录用户</strong>的HOME目录作为当前工作目录，所以<code>ls</code>命令列出的是HOME目录的内容,不要错将<code>~</code>当成根目录。HOME目录是指每个操作用户在Linux系统的个人账户目录，普通用户的HOME目录默认路径在：<code>/home/用户</code>。而root用户的HOME目录，在：<code>/root</code></p><p>功能：切换工作目录</p><p>语法：<code>cd [linux路径]</code></p><p>参数：目标目录，要切换去的地方，不提供默认切换到<strong>当前登录用户HOME目录</strong></p><h3 id="pwd命令">pwd命令</h3><p>print work directory</p><p>功能：展示当前所在的工作目录(绝对路径)</p><p>语法:<code>pwd</code></p><p><img src="https://s2.loli.net/2024/11/26/z7Wtw4VnYUTSGuD.png" alt="002_目录切换命令_04.png"></p><h2 id="文件-夹-操作命令">文件(夹)操作命令</h2><h3 id="mkdir命令">mkdir命令</h3><p>make directory</p><p>功能：创建文件夹</p><p>语法：<code>mkdir [-p] 参数</code></p><ul><li>参数：被创建文件夹的路径</li><li>选项：-p，可选，表示创建前置路径，比如你输入<code>mkdir -p /usr/test/work</code> 但是test文件夹没有创建，那么<code>-p</code>会帮助创建一个test的文件夹，然后再创建work文件夹</li><li>此图第一个d表示这是一个文件夹，后面的与<strong>权限</strong>有关</li></ul><p><img src="https://s2.loli.net/2024/11/26/rC72GPEdxv38otU.png" alt="003_文件操作命令_01.png"></p><h3 id="touch命令">touch命令</h3><p>功能：创建文件，注意要<strong>添加后缀</strong></p><p>语法：<code>touch 参数</code> 参数：被创建的文件路径</p><h3 id="cat命令">cat命令</h3><p>功能：查看文件内容</p><p>语法：<code>cat 参数</code> 参数：被查看的文件路径</p><p><img src="https://s2.loli.net/2024/11/26/h8ZQkoU4KqxFrMR.png" alt="003_文件操作命令_02.png"></p><h3 id="more命令">more命令</h3><p>功能：查看文件，可以支持翻页查看</p><p>语法：<code>more 参数</code> 参数：被查看的文件路径</p><p>在查看过程中：按<strong>空格键翻页</strong> <code>q</code>退出查看 读者可以试试<code>more /etc/services</code> etc(法语et cetera,表示<strong>以及其他内容</strong>)</p><h3 id="cp命令">cp命令</h3><p>copy</p><p>功能：复制文件、文件夹</p><p>语法：<code>cp [-r] 参数1 参数2</code></p><ul><li>参数1，被复制的</li><li>参数2，要复制去的地方</li><li>选项：-r，可选,本意为<strong>递归</strong>(recursion),Linux中能<strong>递归的就是文件夹</strong>了，复制文件夹使用</li></ul><p>示例：cp a.txt test/，复制当前目录a.txt到test文件夹内</p><p><img src="https://s2.loli.net/2024/11/26/khIsrqxdXJYmwgH.png" alt="003_文件操作命令_03.png"></p><h3 id="mv命令">mv命令</h3><p>move</p><p>功能：移动文件、文件夹</p><p>语法：<code>mv 参数1 参数2</code></p><ul><li>参数1：被移动的</li><li>参数2：要移动去的地方，参数2如果不存在，则会进行改名</li></ul><h3 id="rm命令">rm命令</h3><p>remove</p><p>功能：删除文件、文件夹</p><p>语法：<code>rm [-r -f] 参数1 ...参数N</code></p><ul><li>参数：支持多个，每一个表示被删除的，空格进行分隔</li><li>选项：-r，删除文件夹使用</li><li>选项：-f，强制删除(force)，不会给出确认提示，一般root用户会用到,rm命令很危险，小心使用，最好留下快照</li></ul><p><img src="https://s2.loli.net/2024/11/26/2JUPFtE4ISlRM5i.png" alt="003_文件操作命令_04.png"></p><p><strong>通配符</strong></p><p>符号*表示通配符，<br>即匹配任意内容（包含空），示例：</p><ul><li>test*,表示匹配任何以test开头的内容</li><li>*test,表示匹配任何以test结尾的内容</li><li>*test*,表示匹配任何包含test的内容</li></ul><p><img src="https://s2.loli.net/2024/11/26/h16uMsfSqGk9o5r.png" alt="003_文件操作命令_05.png"></p><h2 id="查找命令">查找命令</h2><h3 id="which命令">which命令</h3><p>功能：查看命令的程序本体文件<strong>路径</strong></p><p>语法：<code>which 参数</code> 参数：被查看的命令  比如<code>which cd</code> 返回的是/usr/bin/cd</p><h3 id="find命令">find命令</h3><p>功能：搜索文件</p><p>语法1按文件名搜索：<code>find 路径 -name 参数</code></p><ul><li>路径，搜索的起始路径</li><li>参数，搜索的关键字，同理支持通配符</li><li>按文件大小查找命令：<code>find 起始路径 -size +|-n[KMG]</code>  ±表示大于和小于，n表示数字，KMG表示大小单位。如<code>find / -size -10k</code></li></ul><p><img src="https://s2.loli.net/2024/11/26/vHkjMrWmg8eY62T.png" alt="004_文件查找命令_01.png"></p><h2 id="grep、wc和管道符">grep、wc和管道符</h2><h3 id="grep命令">grep命令</h3><p>功能：过滤关键字，就是搜索关键字，将关键字所在的行展示并标记为红色。</p><p>语法：<code>grep [-n] 关键字 文件路径</code></p><ul><li>选项-n，可选，表示在结果中显示匹配的行的行号。</li><li>参数，关键字，必填，表示过滤的关键字，带有空格或其它特殊符号，建议使用””将关键字包围起来</li><li>参数，文件路径，必填，表示要过滤内容的文件路径，可作为<strong>内容输入端口(就是|)</strong></li></ul><p><img src="https://s2.loli.net/2024/11/26/ki4l2UDp1Cx7Xrt.png" alt="005_过滤命令_01.png"></p><h3 id="wc命令">wc命令</h3><p>功能：统计</p><p>语法：<code>wc [-c -m -l -w] 文件路径</code></p><ul><li>选项，-c，统计bytes数量</li><li>选项，-m，统计字符数量</li><li>选项，-l，统计行(line)数</li><li>选项，-w，统计单词(word)数量</li><li>参数，文件路径，被统计的文件，可作为内容输入端口</li></ul><p><img src="https://s2.loli.net/2024/11/26/Af7culsIYgEryBz.png" alt="005_过滤命令_02.png"></p><p>从左到右分别是行数、单词数、字符数、字节数.</p><h3 id="管道符">管道符|</h3><p>写法：<code>|</code></p><p>功能：<strong>将符号左边的结果，作为符号右边的输入</strong></p><p>示例：<code>cat a.txt | grep itheima</code>，将cat a.txt的结果，作为grep命令的输入，用来过滤<code>itheima</code>关键字</p><p>可以支持嵌套：<code>cat a.txt | grep itheima | grep itcast</code> 还比如<code>ls -l /usr/bin | wc -l</code>表示展示bin文件夹内有多少个文件</p><p><img src="https://s2.loli.net/2024/11/26/QfDMwOpiykCdcg3.png" alt="005_过滤命令_03.png"></p><h2 id="echo、tail和重定向符">echo、tail和重定向符</h2><h3 id="echo命令">echo命令</h3><p>功能：输出内容</p><p>语法：<code>echo 参数</code> 参数：被输出的内容 比如<code>echo &quot;hello world!&quot;</code> 输出内容就是hello world！</p><h3 id="反引号">`反引号</h3><p>功能：被两个反引号包围的内容，会作为命令执行</p><p>示例： echo `pwd`，会输出当前工作目录</p><h3 id="重定向符">重定向符</h3><p>功能：将符号左边的结果，输出到右边指定的文件中去</p><ul><li><code>&gt;</code>，表示覆盖输出</li><li><code>&gt;&gt;</code>，表示追加输出</li></ul><p><img src="https://s2.loli.net/2024/11/26/dxmLvrVRMj9y6T2.png" alt="006_命令_01.png"></p><h3 id="tail命令">tail命令</h3><p>功能：查看文件尾部内容，就是跟踪文件的最新更改。</p><p>语法：<code>tail [-f -num] 参数</code></p><ul><li>参数：被查看的文件</li><li>选项：-f，持续跟踪文件修改。使用两个会话，一个负责修改，一个负责删除，效果会更加明显。</li><li>num表示查看尾部多少行 示例<code>tail -f -10 test.txt</code> 表示从后往前查看test.txt文件内容10行，</li></ul><p><img src="https://s2.loli.net/2024/11/26/gEpJPxZ75VorBm6.png" alt="006_命令_02.png"></p><h3 id="head命令">head命令</h3><p>功能：查看文件头部内容</p><p>语法：<code>head [-n] 参数</code></p><ul><li>参数：被查看的文件</li><li>选项：-n，查看的行数,不写相当于cat命令</li></ul><p><img src="https://s2.loli.net/2024/11/26/5nodCKDBQtxZkRa.png" alt="006_命令_03.png"></p><hr><h2 id="vi编辑器">vi编辑器</h2><p>vim(visual interface,就是文本编辑器)是vi的加强版本，兼容ⅵ的所有指令，不仅能编辑文本，而且还具有shell程序编辑的功能，可以不同颜色的字体来辨别语法的正确性，极大方便了程序的设计和编辑性。</p><p>vi\vim工作模式</p><ul><li>命令模式(Command mode)：所敲的按键编辑器都理解为命令，此时不能自由进行文本编辑</li><li>输入模式(Insert mode)：编辑模式,可以对文件内容进行自由编辑</li><li>底线命令模式(Last line mode):以<code>:</code>开始，通常用于文件的保存和退出</li></ul><p>示意图</p><p><img src="https://s2.loli.net/2024/11/26/3Nh2FL7tEqaWlOV.png" alt="007_vim编辑器_01.png"></p><p>语法：<code>vim 文件路径</code> 没有就会创建</p><table><thead><tr><th>模式</th><th>命令</th><th>描述</th></tr></thead><tbody><tr><td>命令模式(按键都是命令)</td><td>i</td><td>在当前光标位置进入输入模式</td></tr><tr><td>命令模式</td><td>a</td><td>在当前光标位置之后进入输入模式</td></tr><tr><td>命令模式</td><td>I</td><td>在当前行的开头，进入输入模式</td></tr><tr><td>命令模式</td><td>A</td><td>在当前行的结尾，进入输入模式</td></tr><tr><td>命令模式</td><td>o</td><td>在当前光标下一行进入输入模式</td></tr><tr><td>命令模式</td><td>O</td><td>在当前光标上一行进入输入模式</td></tr><tr><td>输入模式(编辑模式)</td><td>esc</td><td>任何情况下输入esc都能回到命令模式</td></tr><tr><td>命令模式</td><td>键盘上、键盘k</td><td>向上移动光标(以行为单位)</td></tr><tr><td>命令模式</td><td>键盘下、键盘j</td><td>向下移动光标(以行为单位)</td></tr><tr><td>命令模式</td><td>键盘左、键盆h</td><td>向左移动光标</td></tr><tr><td>命令模式</td><td>键盘右、键盘1</td><td>向后移动光标</td></tr><tr><td>命令模式</td><td>0</td><td>移动光标到当前行的开头</td></tr><tr><td>命令模式</td><td>$</td><td>移动光标到当前行的结尾</td></tr><tr><td>命令模式</td><td>pageup(PgUp)</td><td>向上翻页</td></tr><tr><td>命令模式</td><td>pangdown(PgDn)</td><td>向下翻页</td></tr><tr><td>命令模式</td><td>/</td><td><strong>进入搜索模式</strong></td></tr><tr><td>命令模式</td><td>n</td><td>向下继续搜索</td></tr><tr><td>命令模式</td><td>N</td><td>向上继续搜索</td></tr><tr><td>命令模式</td><td>dd</td><td>删除光标所在行的内容</td></tr><tr><td>命令模式</td><td>ndd</td><td>n是数字，表示删除当前光标向下n行</td></tr><tr><td>命令模式</td><td>yy</td><td>复制当前行</td></tr><tr><td>命令模式</td><td>nyy</td><td>n是数字，复制当前行和下面的n行</td></tr><tr><td>命令模式</td><td>p</td><td><strong>粘贴复制的内容</strong></td></tr><tr><td>命令模式</td><td>u</td><td><strong>撤销修改</strong></td></tr><tr><td>命令模式</td><td>ctrl+r</td><td>反向撤销修改</td></tr><tr><td>命令模式</td><td>gg</td><td>跳到首行</td></tr><tr><td>命令模式</td><td>G</td><td>跳到行尾</td></tr><tr><td>命令模式</td><td>dG</td><td>从当前行开始，向下全部删除</td></tr><tr><td>命令模式</td><td>dgg</td><td>从当前行开始，向上全部删除</td></tr><tr><td>命令模式</td><td>d$</td><td>从当前光标开始，删除到本行的结尾</td></tr><tr><td>命令模式</td><td>d0</td><td>从当前光标开始，删除到本行的开头</td></tr><tr><td>底线命令模式(涉及文件的退出与保存)</td><td>:wq</td><td>保存并退出</td></tr><tr><td>底线命令模式</td><td>:q</td><td>仅退出</td></tr><tr><td>底线命令模式</td><td>:q!</td><td>强制退出</td></tr><tr><td>底线命令模式</td><td>:w</td><td>仅保存</td></tr><tr><td>底线命令模式</td><td>:set nu</td><td>显示行号</td></tr><tr><td>底线命令模式</td><td>:set nonu</td><td>取消显示行号</td></tr><tr><td>底线命令模式</td><td>:set paste</td><td>设置粘贴模式</td></tr></tbody></table><h2 id="帮助手册">帮助手册</h2><p>如果想要对命令的其它选项进行查阅，可以通过如下方式</p><p>语法：<code>命令 --help</code></p><p>示例：如图列出ls命令的帮助文档。就是不怎么好用ㅍ_ㅍ</p><p><img src="https://s2.loli.net/2024/11/26/tG45neUQlfsiABY.png" alt="008_帮助手册_01.png"></p><p>如果要查看命令的详细手册，可以通过<code>man 命令</code>查看(man &lt;- manual)</p><p>一般下载的Centos默认是英文(不过我的设置成中文＜（＾－＾）＞).如果阅读吃力，可以通过重定向符：man ls &gt; ls-man.txt，输出手册到文件然后通过翻译软件翻译内容查看</p><h1>Linux用户与权限</h1><p>Linux采用多用户的管理模式进行权限管理，而拥有<strong>最大权限的账户名为root</strong>;而普通用户的权限，一般在其HOME目录内是不受限的，出了HOME目录，一般普通用户仅有只读和执行权限，无修改权限。</p><p><img src="https://s2.loli.net/2024/11/26/tl1V9TrCE2wsPGm.png" alt="009_用户与权限_01.png"></p><p>切换用户命令：<code>su [-] [用户名]</code>  或者ctrl+d退回到上一个用户</p><p>为了避免长期使用root导致系统损坏，可以使用<code>sudo</code>命令为普通的命令授权。</p><p>语法：<code>sudo 其他命令</code> 需要为普通用户配置sudo认证。</p><p>未认证的情况</p><p><img src="https://s2.loli.net/2024/11/26/Pd1KLFrSDhfvVpG.png" alt="009_用户与权限_02.png"></p><p><strong>sudo认证方法</strong></p><ol><li><p>切换到root用户，在命令行中输入<code>visudo</code>命令，打开/etc/sudoers</p></li><li><p>文件最后(命令模式按G到文件末尾)添加<code>用户名 ALL=(ALL)   NOPASSWD:ALL</code> 最后退出并保存</p></li></ol><p><img src="https://s2.loli.net/2024/11/26/CHepjnVKaGEbJmL.png" alt="009_用户与权限_03.png"></p><p><img src="https://s2.loli.net/2024/11/26/7jnOQrLTe8m4ayf.png" alt="009_用户与权限_04.png"></p><h3 id="用户管理">用户管理</h3><p><strong>用户与用户组</strong></p><p>不同的用户可以加入多个组中，用组来管理用户。</p><p>创建用户组：<code>groupadd 用户组名</code> 删除用户组: <code>groupdel 用户组名</code></p><p>查看用户组：<code>getend group</code></p><ul><li><p>创建用户<br><code>useradd [-g-d] 用户名</code>:-g指定用户的组，不指定-g,会创建同名组并自动加入，指定-g需要组已经存在，如已存在同名组，必须使用-g;-d指定用户HOME路径，不指定，HOME目录默认在：/home/用户名</p></li><li><p>删除用户<br><code>userdel [-r] 用户名</code> :-r，删除用户的HOME目录。不使用-r删除用户时，HOME目录保留</p></li><li><p>查看用户所属组<br><code>id [用户名]</code>：被查看的用户，如果不提供则查看自身</p></li><li><p>修改用户所属组<br><code>usermod -aG 用户组 用户名</code>： ，将指定用户加入指定用户组</p></li></ul><p><img src="https://s2.loli.net/2024/11/26/k5OTNnxlaDIErQP.png" alt="009_用户与权限_06.png"></p><p>可以看到jerry有两个组，一个是和自己同名的组，一个是之后创建并添加的组。</p><ul><li><p>查看系统中的用户：<code>getent passwd</code></p><p><img src="https://s2.loli.net/2024/11/26/Q7FN6qiXzvDYZrT.png" alt="009_用户与权限_05.png"></p><p>信息格式为：用户名：密码(X):用户ID:组ID:描述信息（无用）：HOME目录：执行终端(默认bash）可以使用<code>getent group</code>查看系统中有哪些组</p></li><li><p>查看系统所有变量： <code>env</code>.</p></li></ul><h3 id="权限信息">权限信息</h3><p>如图所示</p><p><img src="https://s2.loli.net/2024/11/26/wSXPx1LIU36fF5d.png" alt="009_用户与权限_07.png"></p><p>序号1表示文件和文件夹的权限控制信息，序号2中的两个分别表示文件和文件夹所属的<strong>用户</strong>和<strong>用户组</strong>。</p><p>权限讲解如下图</p><p><img src="https://s2.loli.net/2024/11/26/udHDhpZJa1qSw3l.png" alt="009_用户与权限_08.png"></p><p>r\w\x分别代表可读、可写(增删改等)、可执行(可以cd进入)。</p><h3 id="chmod命令">chmod命令</h3><p>语法：<code>chmod [-R] 权限 参数</code></p><p>权限：比如755，表示：<code>rwxr-x--x</code> 示例<code>chmod</code></p><table><thead><tr><th>序号</th><th>意思</th></tr></thead><tbody><tr><td>0</td><td>无任何权限，即–</td></tr><tr><td>1</td><td>仅有x权限，即–x</td></tr><tr><td>2</td><td>仅有w权限，即-w-</td></tr><tr><td>3</td><td>有w和x权限，即-wx</td></tr><tr><td>4</td><td>仅有r权限，即r–</td></tr><tr><td>5</td><td>有r和x权限，即r-x</td></tr><tr><td>6</td><td>有r和w权限，即rw-</td></tr><tr><td>7</td><td>有全部权限，即rwx</td></tr></tbody></table><p>参数：被修改的文件和文件夹</p><p>-R:设置文件夹和其内容全部一样生效。</p><p>示例：<code>chmod u=rwx,g=rx,o=x hello.txt</code> 将文件的权限修改为<code>rwxr-x--x</code> u表示user的权限，g表示组的权限，o表示其他(other)的权限</p><p><img src="https://s2.loli.net/2024/11/26/UG89rT456RCVYdt.png" alt="009_用户与权限_09.png"></p><h3 id="chown命令">chown命令</h3><blockquote><p>此命令只适用于root用户使用</p></blockquote><p>语法：<code>chown [-R] [用户][:][用户组] 文件或文件夹</code></p><p>示例:<code>chown jerry:emp hello.txt</code>  将hello.txt所属的用户修改为jerry,用户组改为emp</p><p><img src="https://s2.loli.net/2024/11/26/iLYpb9XKo4ePIJc.png" alt="009_用户与权限_10.png"></p><h1>Linux实用操作</h1><h2 id="快捷键技巧">快捷键技巧</h2><p><code>ctrl+c</code>:强制停止命令运行，或者是退出当前命令的输入</p><p><code>ctrl+d</code>:退出账户,或者是某些页面</p><p><code>ctrl+l</code>:清屏</p><p>键盘上下键：查看历史命令，同样可以用<code>history</code>，可以通过!命令前缀自动执行上一次匹配前缀的命令，比如<code>!grep</code></p><p><code>ctrl+r</code>:输入内容匹配历史命令，是就回车；左右键得到此命令</p><table><thead><tr><th>快捷键</th><th>作用</th></tr></thead><tbody><tr><td>ctrl+c</td><td>强制停止命令运行，或者是退出当前命令的输入</td></tr><tr><td>ctrl+d</td><td>退出账户,或者是某些页面</td></tr><tr><td>ctrl+l</td><td>清屏</td></tr><tr><td>键盘上下键</td><td>查看历史命令，同样可以用<code>history</code>，可以通过!命令前缀自动执行上一次匹配前缀的命令，比如<code>!grep</code></td></tr><tr><td>ctrl+r</td><td>输入内容匹配历史命令，是就回车；左右键得到此命令</td></tr><tr><td>ctrl+a</td><td>跳到命令开头</td></tr><tr><td>ctrl+e</td><td>跳到命令结尾</td></tr><tr><td>ctrl+左键</td><td>向左跳一个单词</td></tr><tr><td>ctrl+右键</td><td>向右跳一个单词</td></tr></tbody></table><h2 id="安装软件">安装软件</h2><p>有两种方式，一种是自行下载安装包，另一种是在系统的“应用商店”内下载安装。</p><p>yum.RPM包软件管理器，用于自动化安装配置Linux软件，并可以自动解决依赖问题</p><p>在Centos中安装。</p><ul><li><code>yum [install remove search] [-y] 软件名称</code>；install 安装；remove 卸载；search 搜索；-y，自动确认。常见的格式有.exe .pkg .rpm等。注意yum需要root权限且需要联网</li></ul><blockquote><p>由于Centos7在24年6月不再更新，需要自行配置yum源。方法请自行Google。</p></blockquote><p>在Ubuntu系统使用“应用商店”——apt管理器。</p><ul><li><code>apt [install remove search] [-y] 软件名称</code>；install 安装；remove 卸载；search 搜索；-y，自动确认。常见的格式有 .deb等。同样需要root权限且要联网。</li></ul><h2 id="系统命令">系统命令</h2><h3 id="systemctl">systemctl</h3><p>功能：控制系统服务的启动关闭等，常用于防火墙等的开闭</p><p>语法：<code>systemctl start | stop | restart | disable | enable | status 服务名</code></p><p>常见的服务有NetworkManager,主网络服务;network,副网络服务;firewalld,防火墙服务;sshd,ssh服务(远程登录Linux使用的就是这个服务)</p><p>start，启动|stop，停止|status，查看状态|disable，关闭开机自启|enable，开启开机自启|restart，重启</p><p><img src="https://s2.loli.net/2024/11/26/9ZPWiyB72LVJ4nv.png" alt="010_系统命令_01.png"></p><h3 id="软链接">软链接</h3><p>功能：创建文件、文件夹软链接（快捷方式）</p><p>语法：<code>ln -s 参数1 参数2</code>；参数1：被链接的；参数2：要链接去的地方（快捷方式的名称和存放位置）</p><p><img src="https://s2.loli.net/2024/11/26/PCtAJm78h2lnEjD.png" alt="010_系统命令_02.png"></p><p>图中红色方框部分就是软链接.</p><h3 id="日期及其计算">日期及其计算</h3><p>语法：<code>date [-d] [+格式化字符串]</code></p><ul><li><p>-d 按照给定的字符串显示日期，一般用于日期计算</p></li><li><p>格式化字符串：通过特定的字符串标记，来控制显示的日期格式</p><ul><li><p>%Y   年%y   年份后两位数字 (00…99)</p></li><li><p>%m   月份 (01…12)</p></li><li><p>%d   日 (01…31)</p></li><li><p>%H   小时 (00…23)</p></li><li><p>%M   分钟 (00…59)</p></li><li><p>%S   秒 (00…60)</p></li><li><p>%s   自 1970-01-01 00:00:00 UTC 到现在的秒数</p></li></ul></li></ul><p>示例<code>date &quot;+%Y-%m-%d %H:%M:%S&quot;</code> 以2022-01–01 00:00:00 展示时间</p><p><img src="https://s2.loli.net/2024/11/26/3PBiesFClJNHcoA.png" alt="010_系统命令_03.png"></p><p><strong>计算</strong> 示例<code>date -d &quot;+1 [时间标记]&quot; +%Y%m%d</code> 如果时间标记是day ,则显示后一天的日期;如果时间标记是year，则表示后一年的日期。<code>-</code>表示显示前一天；支持的时间标记为:year\month\day\hour\minutes\second.</p><p><strong>修改</strong>：修改时区为中国时区.</p><p>原理：将系统自带的localtime文件删除，并将/usr/share/zoneinfo/Asia/Shanghai文件链接为localtime文件即可</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">rm -f /etc/localtime</span><br><span class="line">sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime</span><br></pre></td></tr></table></figure><p><strong>同步</strong>：同步时间</p><p>安装：<code>yum install -y ntp</code></p><p>启动管理：<code>systemctl start | stop | restart | status | disable | enable ntpd</code></p><h2 id="IP与主机">IP与主机</h2><p>此部分内容与计算机网络密切相关，建议读者学习和掌握计算机网络相关知识，以下内容会更易理解。</p><h3 id="ip地址">ip地址</h3><p>IPv4格式：a.b.c.d。abcd为0~255的数字，比如192.168.88.102</p><p>特殊IP：127.0.0.1，代指本机 ；0.0.0.0：可以表示本机也可以表示任意IP(看使用场景)</p><p>查看ip：<code>ifconfig</code> <code>ens33：</code>中的inet就是IP，<code>lo:</code>本地回环的网卡 <code>virbr0</code>:虚拟机专用的网卡</p><h3 id="主机名">主机名</h3><p>功能：Linux系统的名称</p><p>查看：<code>hostname</code></p><p>设置：<code>hostnamectl set-hostname 主机名</code></p><p>扩展：<strong>域名解析</strong>：简单来说就是根据输入的域名(比如百度)自动分析出服务器对应的IP地址，然后再访问,而不是先记住IP再访问。也就是说IP与域名之间存在<strong>映射</strong>关系.</p><p><img src="https://s2.loli.net/2024/11/26/cO2PiaVDeMynRCN.png" alt="011_IP与主机_01.png"></p><h3 id="配置VMware固定IP">配置VMware固定IP</h3><p>原因：Linux操作系统，其IP地址是通过<strong>DHCP</strong>服务获取的。<strong>DHCP</strong>:动态获取IP地址，即每次重启设备后都会获取一次，可能导致IP地址频繁变更。这一部分在之前的“初识Linux”中的“Linux固定IP“中讲解过详细步骤，这里只是强调重点。</p><p>核心步骤如下：</p><p>修改文件：<code>vim /etc/sysconfig/network-scripts/ifcfg-ens33</code></p><p>示例文件内容：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">TYPE=&quot;Ethernet&quot;</span><br><span class="line">PROXY_METHOD=&quot;none&quot;</span><br><span class="line">BROWSER_ONLY=&quot;no&quot;</span><br><span class="line">BOOTPROTO=&quot;static&quot;# 改为static，固定IP</span><br><span class="line">DEFROUTE=&quot;yes&quot;</span><br><span class="line">IPV4_FAILURE_FATAL=&quot;no&quot;</span><br><span class="line">IPV6INIT=&quot;yes&quot;</span><br><span class="line">IPV6_AUTOCONF=&quot;yes&quot;</span><br><span class="line">IPV6_DEFROUTE=&quot;yes&quot;</span><br><span class="line">IPV6_FAILURE_FATAL=&quot;no&quot;</span><br><span class="line">IPV6_ADDR_GEN_MODE=&quot;stable-privacy&quot;</span><br><span class="line">NAME=&quot;ens33&quot;</span><br><span class="line">UUID=&quot;1b0011cb-0d2e-4eaa-8a11-af7d50ebc876&quot;</span><br><span class="line">DEVICE=&quot;ens33&quot;</span><br><span class="line">ONBOOT=&quot;yes&quot;</span><br><span class="line">IPADDR=&quot;192.168.88.131&quot;# IP地址，自己设置，要匹配网络范围</span><br><span class="line">NETMASK=&quot;255.255.255.0&quot;# 子网掩码，固定写法255.255.255.0</span><br><span class="line">GATEWAY=&quot;192.168.88.2&quot;# 网关，要和VMware中虚拟网络编辑器中的配置一致</span><br><span class="line">DNS1=&quot;192.168.88.2&quot;# DNS1服务器，和网关一致即可</span><br></pre></td></tr></table></figure><h2 id="网络传输">网络传输</h2><h3 id="ping命令">ping命令</h3><p>测试网络是否联通</p><p>语法：ping [-c num] 参数：-c,检查的次数，不使用-c选项，将无限次数持续检查;ip或主机名，被检查的服务器的ip地址或主机名地址 示例<code>ping -c 3 www.baidu.com</code></p><p><img src="https://s2.loli.net/2024/11/26/zNv1YklJrU67d8n.png" alt="012_网络传输_01.png"></p><h3 id="wget命令">wget命令</h3><p>wgt是非交互式的文件下载器，可以在命令行内下载网络文件<br>语法：<code>wget [-b] url</code>选项：-b,可选，后台下载，会将日志写入到当前工作目录的wget-log文件;urL,下载链接<br>示例：<code>wget -b http://archive.apache.org/dist/hadoop/common/hadoop-3.3.0/hadoop-3.3.0.tar.gz</code> 监视后台下载进度 :<code>tail -f wget-log</code></p><h3 id="curl命令">curl命令</h3><p>curl可以发送http网络请求，可用于：下载文件、获取信息等,本质和浏览器访问网页是一样的<br>语法：<code>curl [-O] ur1</code><br>选项：-O,用于下载文件，当url是下载链接时，可以使用此选项保存文件<br>参数：url,要发起请求的网络地址</p><p>示例:<code>curl -O http://archive.apache.org/dist/hadoop/common/hadoop- 3.3.0/hadoop-3.3.0.tar.gz</code></p><h3 id="端口">端口</h3><p>计算机程序之间的通讯，通过IP只能锁定计算机，而端口是更加精确的“地址”，能够锁定计算机上具体的程序，便于程序之间的沟通。</p><p>Linux的端口分类如下</p><ul><li>公认端口：1~1023，通常用于一些系统内置或知名程序的预留使用，如SSH服务的22端口HTTPS服务的443端口，非特殊需要，不要占用这个范围的端口</li><li><strong>注册端口</strong>：1024~49151，通常可以随意使用，用于松散的绑定一些程序\服务。</li><li>动态端口：49152~65535，通常不会固定绑定程序，而是当程序对外进行网络链接时，用于临时使用。</li></ul><p><img src="https://s2.loli.net/2024/11/26/nAf3gcTG9sJKXVb.png" alt="012_网络传输_02.png"></p><h3 id="nmap命令">nmap命令</h3><p>查看端口占用情况</p><blockquote><p>由于Centos停止更新，镜像源波动大，其网络下载困难较大。</p></blockquote><p>下载：<code>yum -y install nmap</code></p><p>语法：<code>nmap 被查看的IP地址</code></p><p>或者也可以使用<code>netstat</code>命令查看端口的占用情况</p><p>语法：<code>netstat -anp | grep 端口号</code> ,需要实现安装netstat</p><h2 id="进程">进程</h2><p>操作系统为管理运行的程序，每一个程序在运行的时候，就会被操作系统注册为系统中的一个进程，并且会为每一个进程都分配一个独有的进程ID(PID)。</p><h3 id="ps命令">ps命令</h3><p>功能：查看进程信息</p><p>语法：<code>ps -ef</code>，查看全部进程信息，可以搭配grep做过滤：<code>ps -ef | grep xxx</code></p><p>示例如下图</p><p><img src="https://s2.loli.net/2024/11/26/ACGYa6mJMNsoyv7.png" alt="013_进程_01.png"></p><p>从左到右分别是：UID是指进程所属的用户ID|PID：进程的进程号ID|PPID:进程的父ID(启动此进程的其它进程）|C:此进程的CPU占用率（百分比）|STIME:进程的启动时间|TTY:启动此进程的终端序号，如显示？，表示非终端启动|TIME :进程占用cpu的时间|CMD：进程的启动路径或者命令。</p><h3 id="kill命令">kill命令</h3><p>语法：<code>kill [-9] 进程ID</code> -9表示强制关闭进程，进程ID可以通过ps和管道符命令实现</p><p><img src="https://s2.loli.net/2024/11/26/xiF2dqn6Mm1G9wz.png" alt="013_进程_02.png"></p><h2 id="主机状态">主机状态</h2><h3 id="top命令">top命令</h3><p>功能：查看主机运行状态。 相当于任务管理器</p><p>语法：<code>top</code>，查看基础信息，按<code>q</code>退出</p><p>示意图如下</p><p><img src="https://s2.loli.net/2024/11/26/F45XC1OepbRAjrx.png" alt="014_主机状态_01.png"></p><p>解释：</p><ul><li>第一行：top:命令名称，08:31:30：当前系统时间，up 38 min:启动了38分钟，1 users:1个用户登录，load average:1、5、15分钟负载</li><li>第二行：Tasks:244个进程，1 running:1个进程子在运行，243 sleeping:243个进程睡眠，0个停止进程，0个僵尸进程</li><li>第三行：%Cpu(s):CPU使用率，us:用户CPU使用率，sy:系统CPU使用率，ni:高优先级进程占用CPU时间百分比，id:空闲CPU率，wa:IO等待CPU占用率，hi:CPU硬件中断率，Si:CPU软件中断率，st:强制等待占用CPU率</li><li>第四、五行：Kib Mem:物理内存，total:总量，free:空闲，used:使用，buff/cache:buff和cache占用，KibSwap:虚拟内存（交换空间），total:总量，free:空闲，used:使用，buff/cache:buff和cache占用</li></ul><p>表格解释</p><table><thead><tr><th>符号</th><th>含义</th></tr></thead><tbody><tr><td>PID</td><td>进程ID</td></tr><tr><td>USER</td><td>进程所属用户</td></tr><tr><td>PR</td><td>进程优先级，越小越高</td></tr><tr><td>NI</td><td>负值表示高优先级，正表示低优先级</td></tr><tr><td>VIRT</td><td>进程使用虚拟内存，单位KB</td></tr><tr><td>RES</td><td>进程使用物理内存，单位KB</td></tr><tr><td>SHR</td><td>进程使用共享内存，单位KB</td></tr><tr><td>S</td><td>进程状态(S休眠，R运行，Z僵死状态，N负数优先级，I空闲状态)</td></tr><tr><td>%CPU</td><td>进程占用CPU率</td></tr><tr><td>%MEM</td><td>进程占用内存率</td></tr><tr><td>TIME+</td><td>进程使用CPU时间统计，单位10毫秒</td></tr><tr><td>COMMAND</td><td>进程的命令或者名称或程序文件路径</td></tr></tbody></table><p>可用选项</p><table><thead><tr><th>选项</th><th>功能</th></tr></thead><tbody><tr><td>-p</td><td>只显示某个进程的信息</td></tr><tr><td>-d</td><td>设置刷新时间，默认是5s</td></tr><tr><td>-c</td><td>显示产生进程的完整命令，默认是进程名</td></tr><tr><td>-n</td><td>指定刷新次数，能如top -n 3,刷新输出3次后退出</td></tr><tr><td>-b</td><td>以非交互非全屏模式运行，以批次的方式执行top,一般配合-n指定输出几次统计信息，将输出重定向到指定文件，比如<code>top -b -n 3 &gt; /tmp/top.tmp</code></td></tr><tr><td>-i</td><td>不显示任何闲置(idle)或无用(zombie)的进程</td></tr><tr><td>-u</td><td>查找特定用户启动的进程</td></tr></tbody></table><p>top的交互式选项</p><p>可以看如下黑马程序员的ppt图</p><p><img src="https://image-set.oss-cn-zhangjiakou.aliyuncs.com/img-out/2022/10/27/20221027221354.png" alt="image-20221027221354137"></p><h3 id="df命令">df命令</h3><p>查看磁盘占用</p><p>语法：<code>df [-h]</code></p><p><img src="https://s2.loli.net/2024/11/26/d3uNpVbgrx4cWJS.png" alt="014_主机状态_02.png"></p><p>还有iostat命令</p><p>语法:<code>iostat [-x] [num1] [num2]</code> -x，显示更多信息;num1：数字，刷新间隔，num2：数字，刷新几次</p><p><img src="https://s2.loli.net/2024/11/26/oIstSuHzTYJR9OU.png" alt="014_主机状态_03.png"></p><p>具体更多信息看图</p><p><img src="https://s2.loli.net/2024/11/26/nx7sgDH2KvNU5rJ.png" alt="014_主机状态_04.png"></p><h3 id="网络监控">网络监控</h3><p>语法:<code>sar -n DEV num1 num2</code> -n表示查看网络，DEV表示查看网络接口。num1是刷新间隔(不填就查看一次结束)，num2是查看次数(不填无限次数)。</p><p><img src="https://s2.loli.net/2024/11/26/LaeOGzDKVkgxnMd.png" alt="014_主机状态_05.png"></p><h2 id="环境变量">环境变量</h2><p>环境变量是操作系统(Windows、Linux、Mac)在运行的时候，记录的一些关键性信息，用以辅助系统运行。比如说要执行cd命令，系统就在PATH环境变量里面的路径找cd的程序(因为cd命令的本体就是：/usr/bin/cd 这个程序文件)，找不到的时候再从当前路径开始查找。配置过<strong>Java</strong>的同学应该有体会。</p><p>查看环境变量：<code>env</code></p><ul><li>临时设置：export 变量名=变量值 ，变量值一般是路径，比如<code>export PATH=$PATH:/home/itheima/myenv</code> 将myenv临时添加到环境变量中</li></ul><p><img src="https://s2.loli.net/2024/11/26/owqTVdjlNX2agiu.png" alt="015_环境变量_01.png"></p><ul><li>永久设置：<ul><li>针对用户，设置用户HOME目录内：<code>.bashrc</code>文件</li><li>针对全局，设置<code>/etc/profile</code></li></ul></li></ul><p>并通过语法source配置文件进行立刻生效</p><h3 id="PATH变量">PATH变量</h3><p>记录了执行程序的搜索路径,可以将自定义路径加入PATH内，实现自定义命令在任意地方均可执行的效果</p><p><img src="https://s2.loli.net/2024/11/26/nSWo8sEhaUz1xHL.png" alt="015_环境变量_02.png"></p><h3 id="符号">$符号</h3><p>可以取出指定的环境变量的值</p><p>语法：<code>$变量名</code></p><p>示例：</p><p><code>echo $PATH</code>，输出PATH环境变量的值</p><p><code>echo $&#123;PATH&#125;ABC</code>，输出PATH环境变量的值以及ABC</p><p>如果变量名和其它内容混淆在一起，可以使用${}</p><h2 id="压缩与解压">压缩与解压</h2><h3 id="文件上传与下载">文件上传与下载</h3><p>可以安装<a href="https://www.xshell.com/zh/">xfcp软件</a>进行文件上传，方法和Xshell大同小异。</p><p>在Linux中常见的压缩格式为tar、grip和zip格式。</p><h3 id="tar命令">tar命令</h3><p><code>tar [-c -v -x -f -z -C] 参数1 参数2 ... 参数N </code></p><ul><li>-z表示使用gzip(.gz)，不写就是.tar格式</li><li>-v显示压缩和解压过程，用于查看进度</li><li>-c创建压缩文件、用于压缩模式</li><li>-x解压模式</li><li>-f要创建的文件或者要解压的文件，必须在所有选项中的最后一个</li><li>-C：要单独使用，与其他参数隔开。选择解压的目的地，用于解压模式</li></ul><p>示例：压缩<code>tar -zcvf test.tar.gz 1.txt 2.txt</code> 将两个txt文件压缩到test.tar.gz内。使用gzip模式。解压：<code>tar -zxvf test.tar.gz -C /home/Tom</code> 将.gz文件解压到指定目录</p><h3 id="zip命令与unzip命令">zip命令与unzip命令</h3><p>语法：<code>zip [-r] 参数1 参数2 参数N</code> -r，被压缩的包含文件夹时，需要使用-r，也就是里面的东西都压缩进来。</p><p>示例：<code>zip -r test.zip a b.txt c.txt</code> 将后面两个txt文件和a文件夹压缩到test.zip文件内。</p><p>语法：<code>unzip [-d] 参数</code> -d指定要解压的位置，参数是被解压的zip压缩包文件。</p><h2 id="后续学习">后续学习</h2><p>读者在学习完Linux基础之后根据自己的需求学习如何在Linux中安装对应的软件(比如mysql、IDEA等)。可以参考黑马程序员的资料</p><h1>参考</h1><p><strong>软件资源</strong></p><ol><li>Xshell：<a href="https://www.xshell.com/zh/free-for-home-school/">家庭/学校免费 - NetSarang Website (xshell.com)</a></li><li>Linux相关发行版：<a href="https://mirrors.tuna.tsinghua.edu.cn/help/centos-vault/">清华大学开源软件镜像站</a></li><li>vmware station:<a href="https://partnerportal.broadcom.com/">博通</a></li></ol><p><strong>参考视频和教程</strong></p><ol><li><a href="https://blog.csdn.net/weixin_74195551/article/details/127288338">安装虚拟机（VMware）保姆级教程（附安装包）</a></li><li><a href="https://www.bilibili.com/video/BV1Sv411r7vd?vd_source=bb8dacb993f11c0e39f8147c98a2894c">【小白入门 通俗易懂】韩顺平 一周学会Linux</a> ,注意韩顺平老师的视频是2021年的，视频中有些网站已经失效，请自行Google或百度查找。</li><li><a href="https://www.bilibili.com/video/BV1n84y1i7td?p=3&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">黑马程序员新版Linux零基础快速入门到精通，全涵盖linux系统知识、常用软件环境部署、Shell脚本、云平台实践、大数据集群项目实战等</a></li></ol><p><strong>参考书籍和资料</strong></p><ol><li><a href="https://www.linuxcool.com/">Linux命令大全(手册) – 真正好用的Linux命令在线查询网站</a> 这个是学Linux必备的，相比某度、CSDN更加简洁，但是如果要更加细节的解释可能还是要依靠CSDN或者Google等搜索引擎。</li><li>黑马程序员资料：<a href="https://yun.itheima.com/course/1013.html">Linux零基础快速入门到精通</a></li></ol>]]></content>
    
    
    <summary type="html">教你学会Linux的基础知识，为服务器搭建、前后端开发和运维测试等打基础</summary>
    
    
    
    <category term="Linux" scheme="https://lloydkai.cn/categories/Linux/"/>
    
    
    <category term="Linux" scheme="https://lloydkai.cn/tags/Linux/"/>
    
    <category term="服务器" scheme="https://lloydkai.cn/tags/%E6%9C%8D%E5%8A%A1%E5%99%A8/"/>
    
  </entry>
  
  <entry>
    <title>英语口语(英语兔版)</title>
    <link href="https://lloydkai.cn/posts/oral-english/"/>
    <id>https://lloydkai.cn/posts/oral-english/</id>
    <published>2024-10-13T09:58:53.000Z</published>
    <updated>2026-04-23T01:46:07.210Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/Qy4Edm6fxwKnbsL.jpg" alt></p><h1>英语口语</h1><p>💡不要用中文去替代英文中独有的，但是中文中缺失的音。</p><h1>三种常用的音标</h1><p>国际音标(IPA):</p><p>KK音标：主要是美式音标，方便美式英语的注音。</p><p>DJ音标：主流音标，口语练习的主要音标。<strong>本文后面不加说明的都是练习的DJ音标(IPA88)</strong></p><p>对于非英语专业或者是语言研究的人来说，我们只需要在学习音标的是能认出这是属于哪一类的音标即可，音标终究是用来帮助发音的。</p><h1>全部音标发音</h1><p>视频如下。</p><div style="position: relative; width: 100%; height: 0; padding-bottom: 75%;">    <iframe src="//player.bilibili.com/player.html?isOutside=true&aid=552211531&bvid=BV1vi4y1C73C&cid=547518386&p=1&autoplay=0" scrolling="no" border="0" frameborder="no" framespacing="0" high_quality="1" allowfullscreen="true" style="position:absolute; height: 100%; width: 100%;">    </iframe></div><h1>发音讲解</h1><p><strong>以元音和辅音分</strong>：</p><p>元音：就是在发音时不受阻碍(如嘴唇张开，但还是会受到舌头的影响)发出的音。辅音与元音相反。注意这里的舌位指的是舌头在发音时隆起的最高点，舌头太高，舌位就高。</p><p>影响元音三要素：圆唇度(嘴巴”o“的程度)，舌位高低，舌位前后。</p><p><strong>以清音和浊音分</strong>：<br>清音与浊音：声带不振动的音就是清音。反之就是浊音。</p><p>示意图如下</p><table><thead><tr><th></th><th>元音</th><th>辅音</th></tr></thead><tbody><tr><td>浊音</td><td>粗略认为所有的元音都是浊元音</td><td>浊辅音</td></tr><tr><td>清音</td><td>\</td><td>清辅音</td></tr></tbody></table><h2 id="元音">元音</h2><blockquote><p>以下都是DJ音标</p></blockquote><h3 id="单元音">单元音</h3><p>注意：后面在音标中的的：不是其正确写法，只是markdown文件难以展现，具体写法还是见参考部分的第一个链接，后面的也是这样。</p><ul><li><strong>/i:/</strong></li></ul><p>bee、fee、pea、read、meat、lead</p><p>发音时不圆唇，注意舌位更高，嘴角要向两边拉开，带点微笑的感觉。</p><ul><li><strong>/ɪ/</strong></li></ul><p>bit、fit、pit、lit、hit、fish</p><p>注意舌位更低，舌尖在下齿后方，比/i:/更放松，嘴角没有那么咧开。</p><p>注意区分，它<strong>不仅仅是把/i:/的时长缩短</strong>，有些美国人发音舌位会更低。有点像是军训时教官说的“一”。</p><ul><li><strong>/u:/</strong></li></ul><p>too、food、loose、prove、moon、soon</p><p>/u:/<strong>口型没有那么圆,而是更扁</strong>,嘴角向两边拉伸，发音部位靠口腔后部。(不要误发成yu)</p><ul><li><strong>/ʊ/</strong></li></ul><p>book、look、good、took、bush、would</p><p>发/ʊ/时,嘴唇没那么撅，更放松时长更短,发音更靠后。/ʊ/并不仅仅是把长音/u:/短着读，/u:/的唇形像两边拉开,而/ʊ/唇形更圆,更放松。</p><ul><li><strong>/e/</strong></li></ul><p>bed、get、pet、let、met、set</p><p>双唇自然张开，口腔放松。舌尖在下牙齿后方，舌面平放</p><ul><li><strong>/ɜ:/</strong></li></ul><p>her、person、learn、bird、word、fur、urgent</p><p>嘴自然张开，唇和舌自然放松，要确保发音时间够长，是重读的长音。如果发音不重读，更短就变成了/ə/ ，在单词中的拼写有er、ear、ir、or、ur等。</p><p>在<strong>美式</strong>英语中会r化，写作/ɜ:r/，是美式英语最显著的特征之一。</p><ul><li><strong>/ə/</strong></li></ul><p>a-about balloon、e-taken problem、i-family pencil、o-memory freedom、u-supply support、y-syringe analysis 这些字母在单词内发音的时候都发/ə/</p><p>嘴自然张开,唇和舌都自然放松不要重读,轻轻地让气流冲出声带自然读出重读,变长→/ɜ:/，它是英语中出现频率它是英语最高，最特殊,最重要的schwa(中央元音或中性元音)。让说话者在不需要强调某个音时用它代替，为了在某个音上减少所花时间，<strong>弱化</strong>成一个中性的默认音。有时候/ə/甚至省略不读。</p><ul><li><strong>/ʌ/</strong></li></ul><p>but、hut、must、son、ton、done</p><p>舌尖在下牙齿后方，舌头平放发音靠口腔中后方，类似于啊但是口型没有那么大,时长更短，英美发音不同。</p><p><strong>美音</strong>/ʌ/和中央元音/ə/区别在于，/ʌ/只出现在重读音节中，而/ə/只出现在轻读音节中。两者一般不做舌位上的区分，区别在于是否重读,在美音中的发音不是在口腔中后方，而是在口腔中间，也就说比英音靠前。</p><ul><li><strong>/ɔ:/</strong></li></ul><p>caught、bought、law、saw、door、four</p><p>嘴唇要撅起来，圆而外凸,肌肉较为紧张，口腔后方发音。</p><p><strong>美音</strong>中/ɔ/没有英音那样圆形外凸，更靠近汉语拼音ao而不是o，如果这个音后面跟字母r，美音中往往r化。</p><ul><li><strong>/æ/</strong></li></ul><p>bad、fat、pat、lad、mat、sat</p><p>最容易读错的音之一，口型一定要张大，饱满，嘴角也要向两边拉伸。舌端在下牙齿后方，同时发出/ɑ:/和/e/这两个音。</p><ul><li><strong>/ɑ:/</strong></li></ul><p>father、fast、glass、car、park、mark</p><p>/ɑ:/的口型比“啊”更大,发音更靠口腔后部(舌根处)发音，时长要足够长。</p><ul><li><strong>/ɒ/</strong></li></ul><p>top、hot、lot、box、stop、wash</p><p>/ɒ/和普通话的凹(ao)相似,但并不相同发/ɒ/时,嘴型更小,时间更短,凹有口型变化，/ɒ/没有。</p><p>在<strong>美音</strong>中一般读作/ɑ:/，也是英式英语和美式英语主要区别之一。</p><h3 id="双元音">双元音</h3><ul><li><strong>/eɪ/</strong></li></ul><p>make、date、cake、safe、play、plane</p><p>/e/和/ɪ/一前一后快速紧密发出，或者理解为从/e/向/ɪ/平滑发音。发这个音口腔是有变化的。</p><ul><li><strong>/ɔɪ/</strong></li></ul><p>boy、toy、soy、voice、noise、moist</p><p>/ɔ:/变短后和/ɪ/一前一后快速紧密发出，或者理解为从/ɔ:/向/ɪ/发音，发这个音口腔是有变化。</p><ul><li><strong>/aɪ/</strong></li></ul><p>bike、nice、time、lick、site、life</p><p>/a/和/ɪ/一前一后快速紧密发出，或者理解为从/a/向/ɪ/发音，发这个音口腔是有变化的，口型更加饱满。</p><ul><li><strong>/aʊ/</strong></li></ul><p>how、cow、allow、house、loud、mouse</p><p>/a/和/ʊ/一前一后快速紧密发出，发这个音口腔是有变化的，口型更饱满更长。</p><ul><li><strong>/əʊ/</strong></li></ul><p>open、hope、post、coat、boat、soap</p><p>/ə/和/ʊ/一前一后快速紧密发出，发这个音口腔是有变化的，嘴唇有收缩的，英音的起始音位比**美音/oʊ/**更靠前。</p><ul><li><strong>/ʊə/</strong></li></ul><p>tour、poor、moor、pure、cure、lure</p><p>/ʊ/和/ə/一前一后快速紧密发出，发音一定要连贯。读音在英音中包含/ʊə/的词基本上都包含字母r，在<strong>美音</strong>中会r化。</p><ul><li><strong>/eə/</strong></li></ul><p>hair、pair、chair、fare、care、dare</p><p>/e/和/ə/一前一后快速紧密发出，发音一定要连贯，注意这个/ə/可不等于/r/.</p><ul><li><strong>/ɪə/</strong></li></ul><p>area、idea、beer、dear、fear、here</p><p>/ɪ/和/ə/一前一后快速紧密发出，发音一定要连贯。请注意,如果是读英音，单词拼写即使出现字母r，单词内部也不会r化，如果是读<strong>美音</strong>，只有单词内部出现r，才有可能r化。美音中如出现r，则对应读音为/ɪr/如不出现r，则一样。如果单词内部没有r，则英音美音都是/ɪə/，比如idea。</p><h2 id="辅音">辅音</h2><p>概念解读(辅音三阶段)：成阻：气流被阻塞；持阻：气流持续往外冲，但仍被阻塞；除阻：阻塞被去除，气流冲出；</p><p>辅音三要素：清浊，调音部位、调音方式</p><blockquote><p>很多中式发音就是因为喜欢在字母后面加上其他的音，比如s后面加i变成”子“please读成普利子</p></blockquote><ul><li><strong>/p/ /b/</strong></li></ul><p>peak beak、pet bed、pig big、rapid rabbit、lap lab、speak beak</p><ol><li>如果p后有元音，比如: peak就是<strong>送气音</strong></li><li>如果p紧跟s，比如: speak就是<strong>不送气音</strong></li><li>如果p后紧跟某些辅音，往往嘴巴闭上就基本完成发音国际音标:[p ]，<strong>几乎听不出这个音</strong>，比如: trapdoor, help me, leap year，<strong>无声除阻音</strong> (也称不完全爆破音)</li></ol><p><strong>/ b/<strong>是</strong>浊辅音</strong>，声带振动。</p><ul><li><strong>/t/ /d/</strong></li></ul><p>tip dip、tea deep、test desk、tap dab、bat bad、bet bed</p><ol><li>如果t后有元音，比如:top就是送气音</li><li>如果t紧跟s，比如: stop就是<strong>不送气音</strong></li><li>如果t后紧跟某些辅音，嘴巴闭上就基本完成发音国际音标: [t ]比如: setback, forget me，<strong>无声除阻音</strong>。</li></ol><p>如果想要知道音标的音位变体，见参考“英语兔”视频部分</p><ol><li>在<strong>美式英语</strong>中，元音之间的字母t(尤其是非重读音节中)，读作<strong>闪音</strong>，国际音标:[ɾ]，舌尖在上牙齿上方硬腭处，阻挡气流,轻轻—弹比如: water, better, little，听起来很像发出了/d/ 的声音。在标准英音中仍读作正常t: water, better, little。</li><li>在<strong>美式英语</strong>中，鼻音/n/之前的t往往读作<strong>喉塞音</strong>，国际音标:[ʔ]，声门阻住气流，像是把声音&quot;卡在喉咙&quot;里一样比如: certain, important, button，在标准英音中仍读作正常t : certain, important, button</li><li>在<strong>美式英语</strong>中，鼻音/n/之后的t往往基本听不见，比如: winter≈winner， interview≈innerview，甚至有的词中, t前后都有鼻音，比如: mountain，在标准英音中仍读作正常t: winter, interview, mountain</li><li>/ d/是浊辅音，声带振动。在美音中，/d /和/t/一样会有<strong>闪音</strong>的读法: metal约等于medal，鼻音也会影响/d/的读音: abandon.</li></ol><ul><li><strong>/k/ /g/</strong></li></ul><p>kit git、kate gate、cup gut、anchor anger、pick pig、peck keg</p><ol><li>如果k后有元音比如:kite，就是送气音</li><li>如果k紧跟s比如: sky，不送气音普通话&quot;该&quot;的声母</li><li>如果k后紧跟某些辅音嘴巴闭上就基本完成发音国际音标: [k ]，比如: dogtor, backdoor, make dinner，<strong>无声除阻音</strong>。</li></ol><ul><li><strong>/m/ /n/ /ŋ/</strong></li></ul><p>map nap、met net、meet neat、room noon、tom run、lime line、sin sing、on long、sun sung</p><ol><li>/m/在元音之前，和普通话&quot;妈&quot;的声母(汉语拼音m)相似。在元音之后，发音方式相似，但只是双唇闭拢发鼻音。</li><li>/n/在元音之前，和普通话&quot;拿&quot;的声母(汉语拼音n)相似/n/要比/m/的舌位高，尤其是舌端部分。在元音之后,发音方式相似，轻微通过鼻子出气。</li><li>/ŋ/和/n/相似,但舌后端抵住软腭，而不像/n/一样舌前端抵住上齿龈。</li></ol><p>普通话中的后鼻音往往没有英语中那么清晰明显</p><ul><li><strong>/f/ /v/</strong></li></ul><p>fat valley、fit visit、ferry very、fest vest、life drive、leaf leave</p><p>/f/和普通话&quot;夫&quot;的声母，基本一样/v/是&quot;声带振动版&quot;的/f/</p><ul><li><strong>/s/ /z/</strong></li></ul><p>sip zip、soon zoom、soup zoo、lesson reason、once lose、peace please</p><p>英语的/s/，/z/都属于所谓<strong>摩擦音</strong>，不同于爆破音，/s/和普通话&quot;斯&quot;的声母(汉语拼音s)一样，/z/和/s/很像，区别就在于/z/发音时<strong>声带振动</strong>。</p><ul><li><strong>/θ/ /ð/</strong></li></ul><p>three there、thin that、thank those、thigh the、bath bathe、breath breathe</p><p>和/s//z/一样，属于摩擦音，不同在于舌尖不在上下牙齿后方，而是在上下齿之间，被轻轻咬住，/θ/ /ð/区别在于/ð/需要<strong>声带振动</strong>。</p><ul><li><strong>/ʃ/ /ʒ/</strong></li></ul><p>mesh measure、fresh pleasure、leash decision、attention occasion、shall usual、shame regime</p><p>/ʃ/ /ʒ/属于摩擦音，/ʃ/ /ʒ/区别在于/ʒ/需要声带振动。</p><ul><li><strong>/tʃ/ /dʒ/</strong></li></ul><p>chuck jug、chop job、choke joke、cheap jeep、catch page、pitch college</p><p>/tʃ/可以理解为由/t/和/ʃ/构成,爆破音/t/和摩擦音/ʃ/同时发出，声带不振动。</p><p>/dʒ/可以理解为由/d /和/ʒ/构成,爆破音/d/和摩擦音/ʒ/同时发出，声带振动，所以也被称作破擦音。</p><ul><li><strong>/h/</strong></li></ul><p>hat、hot、high、home、house、him</p><p>舌面后部抬起接近软腭，形成缝隙,让气流向外通过,声带不振动。</p><ul><li><strong>/w/</strong></li></ul><p>was、why、wide、wet、we、wood</p><p>双唇圈起，向外凸出，气流冲出发音，声带震动，/w/往往听上去像元音/u:/或/ʊ/,所以又被称作半元音，英语w开头的单词基本都是/w/开始。</p><ul><li><strong>/r/</strong></li></ul><p>rat、red、read、rice、right、room、car、her、ear、bore、tour、pure</p><ol><li>英音中，当字母r出现在元音<strong>之前</strong>，双唇突出并<strong>圆唇</strong>,舌尖上扬，气流从舌面上方滑出,声带振动。发英语/r/的音时，舌尖指向上齿龈。</li><li>英音中，当字母r出现在元音<strong>之后</strong>，—般不发音或读作中央元音/ə/</li><li>如果r出现在单词<strong>末尾</strong>，而下一个单词以元音开头,则连读时一般读出，比如:bear it、fear us、gear up</li><li>美音和英音的区别在于:当字母r出现在元音之后，字母r往往会让<strong>元音r化</strong>，而在英音中则一般不发音或读作中央元音/ə/</li></ol><ul><li><strong>/j/</strong></li></ul><p>yes、yard、yellow、young、yoga、use</p><p>舌端往上抬向硬腭，与元音/i:/的舌位相似，但是更高一些。气流从舌面和硬腭之间通过，产生摩擦出声，声带振动。/j/往往听上去像元音/i:/或/ɪ/，所以又被称作半元音。但是/j/的舌端和硬腭靠得更近，有摩擦的感觉。</p><ol><li><strong>/j/的省略：<strong>在</strong>美式英语</strong>中,有些辅音(如/t/，/d/，/n/)后的/j/经常被<strong>省略</strong>，这个被称作yod-dropping(yod就是/j/)</li><li><strong>/j/的融合</strong>：和之前的辅音经常&quot;合在一起读&quot;,这个被称作yod-coalescence，在口语中(尤其是英音口语中)常见, &quot;标准&quot;英语一般尽量避免。有的词中,yod-coalescence已成为标准音，如: educate /'edʒukeɪt/、issue / 'ɪʃu:/ 、azure /'æʒə/</li><li>yod-coalescence也适用于单词之间，比如:Nice to meet you! Would you do it?</li></ol><ul><li><strong>/l/</strong></li></ul><p>清晰L：lack lake like look lose leak、模糊L：help mile all girl school full</p><ol><li>如果l后有元音：舌尖抵住上牙齿后方，让气流从舌两边(两侧)滑出，同时舌尖离开上牙齿后，声带振动，所以/l/被叫做&quot;舌边音&quot;或&quot;舌侧音&quot;（清晰舌边音）</li><li>如果l后没有元音：舌位和元音前的/l/一致，但是舌尖不离开上牙齿，声带振动（模糊舌边音）模糊L要发到位，否则导致连读时不顺畅，或者没法连读。</li><li>字母|还有一个版本:不发音，英语中不少单词中的l都是不发音的，比如:calm、palm、salmon、colonel、folk</li><li>英音美音发音区别:有的包含l的词在英式英语和<strong>美式英语</strong>中发音不同，比如:英音: million, billion, value美音: million, billion, value</li></ol><ul><li><strong>/ts/ /dz/</strong></li></ul><p>bats bands、dates deeds、kites kids、fights friends、hats hands、lots leads</p><ol><li>/ts/可以理解为由/t/和/s/构成。爆破音/t/和摩擦音/s/同时发出，声带不振动。</li><li>/dz/可以理解为由/d/和/z/构成，爆破音/d/和摩擦音/z/同时发出，声带振动。</li></ol><p>所以这两个音被归类为所谓破擦音(爆破＋摩擦)</p><ul><li><strong>/tr/ /dr/</strong></li></ul><p>trip drip、true drew、tree dream、try dry、country laundry、pantry hundred</p><ol><li>/tr/可以理解为由/t/和/r/构成。爆破音/t/和摩擦音/r/同时发出，声带不振动。</li><li>/dr/可以理解为由/d/和/r/构成。爆破音/d/和摩擦音/r/同时发出，声带振动。</li></ol><p>所以这两个音被归类为所谓破擦音(爆破＋摩擦)</p><h1>英语发音技巧</h1><blockquote><p>这些发音技巧能够让你的发音更加地道，同时也能很大程度上提升你的英语听力</p></blockquote><h2 id="连音">连音</h2><p>单词(辅音结尾)+单词(元音开头)如：not at all.(“闹太套”),中文不习惯连读，我们读“我爱天安门”不会像外国人那样连读成“外天门”。这就是英语听不准确的重要口语习惯和原因。也就是说，<strong>辅音单词结尾的辅音要发到位，不加上不存在的元音</strong>，然后自然读下一个单词就能“连读”。</p><p>💡连读不是创造一个音，而是两个音结合产生的结果。试着平滑地读I am，你就会感受到/j/的发音，这就是<strong>连音的本质</strong>。如果<strong>你的发音不标准，就不会自然而然地读出连音</strong>。</p><p><strong>加音规则</strong></p><p>注意是先有加音现象，再总结出规律。</p><ol><li>元音+元音：元音与元音连读容易糊，加上一个之前不存在的“过渡音”使得加音连贯。<ul><li>/u:/, <strong>/ʊ/</strong>,<strong>/aʊ/</strong>, <strong>/əʊ/</strong>+元音:+/w/。如：just do it.</li><li>/i:/,<strong>/ɪ/</strong>,<strong>/eɪ/</strong>,<strong>/aɪ/</strong>,<strong>/ɔɪ/</strong>+元音:+/j/。如： I am.</li><li><strong>/ə/</strong>,<strong>/ɑ:/</strong>,<strong>/ɔ:/</strong>+元音:+/r/。主要是英式英语用，美式英语很少。如 the idea of；美式英语主要是字母r+元音，如bear it.连读但是不加音。</li></ul></li><li>辅音+元音(词尾辅音 + 词首元音）： travel agency</li></ol><h2 id="同化">同化</h2><ol><li>逆行同化(前面的音受到后一个音的影响)<ol><li>无声除阻(不完全爆破)：/k/ /t/ /d/+辅音，爆破音不发音 如:look back</li><li>浊音变清音：如 have to :直接变成/f/+/t/,这样比原来的浊音更好发音。</li><li>双唇化：如in person.受到p这个要闭唇的音印象，读起来变成了 im person。</li></ol></li><li>顺行同化(后面音受到前面影响)<ol><li>复数词尾：如books 一般会读成ks而不是kz。</li></ol></li><li>互相同化：<ol><li>融合发音:/s/+/j/ = <strong>/ʃ/</strong>;例如:God bless you;/z/+/j/ =  <strong>/ʒ/</strong>;例如as you wish;/t/+/j/ = <strong>/tʃ/</strong> ;例如Nice to me you;/d/+/j/ = <strong>/dʒ/</strong>;例如Did you do it?</li><li>辅音延长：当前面一个音和后面一个音是同一个音时。只发一个音(这里的音是指<strong>音标</strong>不是字母)，但是要延长：如fish shop.这里前后都是sh</li></ol></li><li>完全失爆（词尾爆破音( p b t d k g)+ 词首爆破音( p b t d k g)：<ol><li>good question</li></ol></li></ol><h2 id="异化">异化</h2><p>常见于/s/+/t/、/s/+/k/、/s/+/p/的组合。<strong>严格来说不是浊化</strong>，而是将这些音变成不送气的音，但是只是发音的话就是不用考虑这些</p><ol><li>r使前面的元音r化：如door 使前一个r消失，如surprise变成su®prise.</li><li>具体例子sp+元音：<ol><li>How do you spend your leisure time?</li><li>sk+元音：i’m so scared</li><li>st + 元音：Stand up and study hard.</li><li>str+ 元音:  He struck me with a stick</li></ol></li></ol><h2 id="省音">省音</h2><ol><li>偷懒不读某一个或者是一些音：如interesting,这类往往可省可不省，省多少看个人说话习惯。</li><li>必须省音。如debt\subtle\know\knee\write\wrong……这些词中b\k\w都是省略不读的。</li><li>词与词之间省略：比如last year就只读las year.t直接省略。</li><li>还有/t/、/d/等(词尾)爆破音也经常省略。如：have 的/h/(这被称为<strong>h击穿</strong>)。ing中的/g/，比如 Are you listenin’?这里打‘就说明省去了g</li></ol><h2 id="缩读">缩读</h2><p>缩写表示可以缩读：如 I am=I’m,I have=I’ve 这些词往往在英语听力的时候读的很快不容易听到或者是听完整。比如wanna=want to, going to=gonna,because='cause还有许多缩写形式的单词或者短语都是这种形式。还有很多类似的都是，比如don’t know=dunno、give me=gimme、would have would’ve/would’a、you and I=you 'n’l、come on =c’mon</p><h2 id="弱读">弱读</h2><p>弱读非常重要，是中国人听不清英语的关键。<br>弱读不是声音变小，而是将元音改变了,这样能够让语句发音更轻松自然，不至于像中文那样“字正腔圆”导致读起来上气不接下气。</p><p>例句：What <strong>do</strong> you want <strong>to do</strong>?<strong>From</strong> <strong>what</strong> I <strong>can</strong> tell,you <strong>must</strong> be tired <strong>of</strong> it,<strong>but</strong> I’m not,so <strong>would</strong> you like me <strong>to do</strong> it <strong>for</strong> you?<br>/d<strong>ə</strong> t<strong>ə</strong> fr<strong>ə</strong>m w<strong>ə</strong>t k<strong>ə</strong>n m<strong>ə</strong>st <strong>ə</strong>v b<strong>ə</strong>t w<strong>ə</strong>d f<strong>ə</strong>/</p><blockquote><p>弱读时，单词的中间的元音一般会变成中央元音/<strong>ə/</strong></p></blockquote><h2 id="节奏">节奏</h2><p>💡英语是重音等时语言</p><p><strong>英语语句中重读音节之间的时长基本相等</strong>，也就是说英语句中词语所花时间是由重读音节数量决定的。举例：Rabbits | eat | carrots.\A rabbit is | eating some | carrots.\The <strong>rabbit</strong> has been | <strong>eating</strong> some of the | <strong>carrots</strong>.分成三个音节，加粗部分为重读音节<br>也就是说，这是三个音节之间时长相等，根据之间的单词个数决定要不要快速读或者是连读，这样其实也体现了中央元音/ə/的重要性，就是为了和重读音节相对应的。</p><p>总而言之记住一句话：英语句子中的非重读音节数量远远大于重读音节数量。</p><h2 id="语调">语调</h2><p>💡语调基于节奏</p><p>语调就是英语句子声调在哪里升高哪里降低。但是不是中文的四声或者五度标记法。<br>语调就是表达说话人的情感，不需要死记(不一定升调就是提问，降调就是丧气)，多听多说就能理解。</p><h3 id="升调">升调</h3><p>这里用☑表示升调，放在哪个单词后哪个单词就升调，一般用来表达态度/情感/陈述/疑问/强调等</p><p>举例</p><ol><li>一般疑问句：Are you kidding me☑ ？</li><li>陈述形式的提问：Rabbits eat carrot☑ ?</li><li>反义疑问词中的附加问句：you are right,are not you☑ ?</li><li>列举中最后一个元素之前的元素：Are rabbits red☑，yellow☑，blue☑，green☑,or white?</li><li>礼貌请求:Tell me,please☑</li><li>句子中未完成的部分：The rabbit ate a carrot☑ and then slept.</li></ol><h3 id="降调">降调</h3><p>用[\]表示降调</p><ol><li>特殊疑问句(非yes/no问题)：what is your name[\]?</li><li>陈述事实或者回答问题： I see a white rabbit[\].</li><li>感叹：what a beautiful leaf[\]!</li><li>命令：put the girl down[\]!</li><li>列举中最后一个元素：反义疑问句前一部分：Rabbits like to eat,play,sleep and run[\].</li><li>反义疑问句前面一部分：Rabbit eat carrots[\],don’t they?</li><li>作为回答/附和/确认的问句形式：The rabbit ate all the carrots. Did it[\]?</li><li>已经知道提问的答案：can you call me at 6[\].</li><li>问句形式表礼貌，并非真的在问问题：Would you pass me the salt[\]?</li><li>不满、愤怒：Is that what you think[\]?</li></ol><p>参考音节</p><p>TU表示重读，tu表示弱读。同样适用于句子和词组。</p><ol><li>单音节 TU：如two!two?</li><li>双音节 TU tu： 如rabbit!rabbit?</li><li>双音节 tu TU：如sit down!sit down?</li><li>三音节 TU tu tu：如possible!possible?</li><li>三音节 tu TU tu：如computer!computer?</li><li>三音节 tu tu TU：如engineer!engineer?</li></ol><h1>自然拼读(Phonics)</h1><p>就是看字母，<strong>猜读音</strong>。这部分内容属于技巧向，对英语口语与听力有帮助。</p><p>以下内容主要讨论一般情况，特殊情况请参考词典。</p><h2 id="开音节与闭音节">开音节与闭音节</h2><p><strong>概念解析</strong>：</p><p>音节：由音素组合成的<strong>最小</strong>最自然的语音单位，比如rabbit的音节分别是rab和bit。</p><p>闭音节：以辅音结尾的音节。比如baby中的by音节。注意这里的辅音不是指字母而是指音标。</p><p>开音节：以元音结尾的音节。比如baby中的ba音节。</p><p>重读音节：被强调的音节就是重读音节，往往声音更大，元音也被拉长。比如rabbit.其音标为/‘ræbɪt/ 这里的’就是用来标记重读音节的，所以rab音量较大，元音也延长。ˌ为次重读音节，在重读与非重读之间。比如accidental，其音标为/ˌ æksɪ’dentl/</p><p>非重读音节：与重读音节相反。</p><p>相对开音节：以不发音的元音字母e结尾的闭音节。</p><h2 id="单个字母">单个字母</h2><blockquote><p>以下图都是从英语兔公众号下载而来</p></blockquote><p>辅音字母</p><p><img src="https://s2.loli.net/2024/11/26/s6PErIDYCQJL4Z5.png" alt="001_字母发音_01.png"></p><p>元音字母</p><p><strong>单个元音字母在重读开音节里读元音字母本身的读音</strong></p><p><img src="https://s2.loli.net/2024/11/26/ohsaKvIrCBfPZdx.png" alt="001_字母发音_02.png"></p><p><strong>单个元音字母在相对开音节里读元音字母本身的读音</strong> 比如bate</p><h2 id="字母组合">字母组合</h2><p>辅音组合</p><p><img src="https://s2.loli.net/2024/11/26/iCemwkp4ySY6Hjb.png" alt="001_字母发音_03.png"></p><p>元音组合</p><p><img src="https://s2.loli.net/2024/11/26/3BkEcelpLydK2sO.png" alt="001_字母发音_04.png"></p><p>以上这些只是技巧向，真正要学好英语口语还是要大量的输入与输出。</p><h1>参考</h1><ol><li><a href="https://www.jiwake.com/yinbiaofayin/">英语音标发音表-英语48个音标在线读 (jiwake.com)</a></li><li><a href="https://zhuanlan.zhihu.com/p/457728471">【笔记】英语兔的DJ音标整理 - 知乎 (zhihu.com)</a></li><li><a href="https://www.bilibili.com/video/BV1iV411z7Nj?p=28&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">全网最适合中国人的免费音标课(纯干货, 超详细!)</a></li><li><a href="https://www.bilibili.com/video/BV1SZ4y1K7Lr?p=7&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">你必须知道的英语发音技巧(让你的口语更纯正, 更地道!)</a></li><li><a href="https://www.bilibili.com/video/BV14841117gz?p=4&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">英语自然拼读极简教程（免费、简洁、高效 | 半小时内打牢基础</a></li></ol>]]></content>
    
    
    <summary type="html">本文章讲解基础的英语口语知识，旨在帮助读者提高英语口语和听写能力。</summary>
    
    
    
    <category term="English" scheme="https://lloydkai.cn/categories/English/"/>
    
    
    <category term="English" scheme="https://lloydkai.cn/tags/English/"/>
    
  </entry>
  
  <entry>
    <title>英语语法(英语兔版)</title>
    <link href="https://lloydkai.cn/posts/english-grammer/"/>
    <id>https://lloydkai.cn/posts/english-grammer/</id>
    <published>2024-10-11T11:58:55.000Z</published>
    <updated>2026-04-23T01:46:21.922Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/kerNGo78PMwicnV.jpg" alt></p><h1>英语语法综述</h1><p>💡语法的目的在于造句，而英语句子的核心在于动词</p><p>英语中所有的句子都可以视为是简单句的组合，而简单句基本上都服从一个模板：<strong>什么+怎么样</strong>。</p><p>这两个代表不同的句子成分(clause elements)，前者代表主语(subject),后者代表谓语(predicate)，即主语+谓语</p><p>而谓语代表的是广义的动作/发生了什么事,谓语的核心在于谓语<strong>动词</strong>。提醒：谓语≠谓语动词,谓语是除主语之外的，而谓语动词只是一个动词。</p><p><strong>所以要学好语法先从动词开始</strong>。</p><hr><h1>动词(verbs)</h1><h2 id="动词的三大本领">动词的三大本领</h2><ol><li>表示动作的时间</li><li>表示动作的状态</li><li>表示动作的假设，情感等</li></ol><p><strong>动词在五大句型中的作用</strong></p><table><thead><tr><th>作用</th><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>可以独立完成的动作(主语+不及物动词)</td><td>主语+不及物动词</td><td>I sleep</td></tr><tr><td>有一个动作的承受者</td><td>主语+单及物动词(monotransitive verbs)+宾语(object)</td><td>I like you</td></tr><tr><td>有两个动作承受者</td><td>主+双及物动词(ditransitive verbs)+间接宾语+直接宾语</td><td>I will teach you English.这里的<strong>you</strong>是间接宾语，<strong>English</strong>是直接宾语</td></tr><tr><td>只有一个动作承受者,但是需要补充</td><td>主语+复杂及物动词+宾语+补语(complement)</td><td>I think you smart</td></tr><tr><td>非动作</td><td>主语+系动词(link verbs)+(主语)补语/表语</td><td>he looks smart.将smart赋予给主语，再加上系动词的部分意义。</td></tr></tbody></table><p>💡五大句型区分关键在于动词之后需要几个对象才能表达完整意思</p><p><strong>动词分类</strong></p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">一般分类</button><button type="button" class="tab">按动作承受者分类</button><button type="button" class="tab">按状态动作分类</button></div><div class="tab-contents"><div class="tab-item-content active"><table><thead><tr><th>词性</th><th>例子</th></tr></thead><tbody><tr><td>实义动词</td><td>eat</td></tr><tr><td>系动词</td><td>be</td></tr><tr><td>助动词 辅助构成谓语动词</td><td>have</td></tr><tr><td>情态动词</td><td>must</td></tr><tr><td>非谓语动词)不定式、过去分词、现在分词、动名词)</td><td>running</td></tr></tbody></table></div><div class="tab-item-content"><table><thead><tr><th>类型</th><th>例子</th></tr></thead><tbody><tr><td>及物动词</td><td>eat vt.吃</td></tr><tr><td>不及物动词</td><td>run vi.跑</td></tr></tbody></table></div><div class="tab-item-content"><table><thead><tr><th>类型</th><th>例子</th></tr></thead><tbody><tr><td>动作动词</td><td>eat</td></tr><tr><td>状态动词</td><td>feel v.感觉 并没有明显的动作</td></tr></tbody></table></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="动词时态">动词时态</h2><p><strong>时态：时间+状态</strong>。前者表明动作发生的时间(过去，现在，将来和过去将来),后者表明动作发生的状态(进行时、完成时、完成进行时、一般时)。<br>四种动词时间与四种时态排列组合就会产生16种时态。</p><p>完成状态的<strong>理解在于强调“影响”</strong>，比如<code>I have eaten breakfast.</code> 暗示在过去的某个时间到现在(have的时间)我已经吃了早饭，暗示我还不饿。</p><h3 id="现在类">现在类</h3><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">一般现在</button><button type="button" class="tab">现在进行</button><button type="button" class="tab">现在完成</button><button type="button" class="tab">现在完成进行</button></div><div class="tab-contents"><div class="tab-item-content active"><blockquote><p>这里的一般现在严格来说是现在一般时，只是顺序颠倒了一下，后面同理。</p></blockquote><p><strong>含义：表达事实|表达习惯|表达预计发生的事</strong></p><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>+动词原形</td><td>I eat carrots.</td></tr><tr><td>+动词原形+第三人称单数</td><td>she eats carrots.</td></tr><tr><td>事实陈述</td><td>The sun rise in the east 习惯:I play basketball我打篮球(隐含我有打篮球的习惯) 预计发生的事: The bus leaves at 8 PM tonight.</td></tr></tbody></table><p>误区：一般现在不代表现在正在做，I eat carrots. 意思是我吃胡萝卜.<em>一般代表的是一种默认，或者是未指明</em></p></div><div class="tab-item-content"><p><strong>助动词be的变位+动词现在分词</strong></p><table><thead><tr><th>词性</th><th>形式</th></tr></thead><tbody><tr><td>助动词</td><td>1. 系动词 am,is,are…… 2. 作助动词，构成时态</td></tr><tr><td>动词现在分词</td><td>1. 通常：+ing 2. 特殊：变化+ing→不规则变化很多都是为了发音而妥协的。I am lying != I am lieing</td></tr></tbody></table></div><div class="tab-item-content"><p><strong>助动词have的变位+动词过去分词</strong></p><table><thead><tr><th>词性</th><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>Have</td><td>1. 实义动词：有 2. 助动词构成时态</td><td>2. The rabbit has eaten a carrot.</td></tr><tr><td>动词过去分词</td><td>1. 通常：+ed 2. 特殊：变化+ed/不规则变化</td><td>look-&gt;looked/eat-&gt;ate</td></tr></tbody></table></div><div class="tab-item-content"><p><strong>现在完成+进行时==have的变位+been+动词现在分词.意思是已经做了，而且还要继续做  。</strong> 例子：I have been eating carrot.</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>💡时态都是在现在类基础上将时间往前(或后)推移，对应时间更改谓语动词即可。</p><hr><h3 id="过去类">过去类</h3><p>💡本质就是现在类的助动词(或者情态动词、动词等)变换时间(比如have变成had,is变成was,may变成might)</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">一般过去</button><button type="button" class="tab">过去进行</button><button type="button" class="tab">过去完成</button><button type="button" class="tab">过去完成进行</button></div><div class="tab-contents"><div class="tab-item-content active"><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>过去式(规则的一般+ed)</td><td>look-&gt;looked</td></tr><tr><td>不规则变化(不用刻意记，用来写的并不多)</td><td>come-&gt;came</td></tr></tbody></table></div><div class="tab-item-content"><p><strong>助动词be的变位+动词现在分词</strong></p><table><thead><tr><th>解释</th><th>例子</th></tr></thead><tbody><tr><td>注意be的变位不再是现在时态的只变人称，还要变为相应的时态。<em>即be变成对应的人称过去式</em></td><td>she was watching TV</td></tr><tr><td>区别：现在完成vs一般过去 前者强调的是动作完成了吗，后者强调的是动作有没有发生。</td><td>前者的例句I have gone to Beijing.(我已经去了北京(暗示没回来))，后者的例句I went to Beijing.(我去过北京)暗示回来了))</td></tr></tbody></table></div><div class="tab-item-content"><p><strong>同理，见现在完成部分，是助动词have的变位(只有had)+动词过去分词</strong></p></div><div class="tab-item-content"><p><strong>had+been+动词的现在分词</strong></p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><p>不规则动词列表：在 本电脑根目录下obsidian内附件集/英语/文档/不规则变化.pdf。读者可以点击此链接<a href="https://www.yingyutu.com/">英语兔 (yingyutu.com)</a> 在英语兔公众号下载对应笔记。</p><hr><h3 id="将来类">将来类</h3><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">一般将来</button><button type="button" class="tab">将来进行</button><button type="button" class="tab">将来完成</button><button type="button" class="tab">将来完成进行时</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>一般用于非常确定会发生的事</strong></p><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>will(或者是shall)+动词原形</td><td>I will eat a carrot.</td></tr><tr><td>助动词be的变位+going+to+动词原形</td><td>1. 原样：I am going to take a shower. 2. 省去going：you are to eat a carrot 3. 用about代替going：I am about to chat with him.</td></tr></tbody></table></div><div class="tab-item-content"><p><strong>will+be+动词的现在分词)在将来的某一个时间段，某个动作正在进行)</strong>  例如：I will be eating a carrot for lunch tomorrow from 1 PM to 3 PM</p></div><div class="tab-item-content"><p><strong>will+have+动词的过去分词</strong> 例子(以下用<strong>ex</strong>表示)：If suddenly you forget me. Do not look for me,for I shall already have forgotten you.</p></div><div class="tab-item-content"><p><strong>will+have+been+动词的现在分词</strong> ex:I will have been eating carrots for 2 hours by 3 PM tomorrow.这里要表达的意思就是：我确定明天下午三点钟时，我不但已经吃了俩钟头胡萝卜(也就是从明天下午1点开始吃)而且还要继续吃.</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><hr><h3 id="过去将来类">过去将来类</h3><p><em>过去将来可能是现在的过去，也可能是现在的未来。</em></p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">过去将来一般</button><button type="button" class="tab">过去将来进行</button><button type="button" class="tab">过去将来完成</button><button type="button" class="tab">过去将来完成进行</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>would+动词原形|或者是助动词be的变位+going to。</strong></p><table><thead><tr><th>would形式</th><th>例子</th></tr></thead><tbody><tr><td>Will的过去式</td><td>I would eat a carrot.</td></tr><tr><td>虚拟语气，表达和事实相反。</td><td>I said I would eat a carrot for lunch. 我之前就说过我会午饭吃胡萝卜，而午饭时间对于之前我说那句话的时间来说是在将来，但至于现在午饭时间有没有到，不得而知</td></tr></tbody></table></div><div class="tab-item-content"><p><strong>同理，在将来进行时前面+would</strong></p></div><div class="tab-item-content"><p><strong>同理，在将来完成时前面+would</strong></p></div><div class="tab-item-content"><p><strong>同理，在将来完成进行前面+would。</strong></p><p>中文举例：在这之前，张三说下个月的某一天，你一定会看到我犯完罪，而且还会一直犯下去 在这之前表示过去，说下个月的某一天表明是将来，结合就是过去将来(时间),而犯完罪而且犯下去表明动作已经完成，而且会继续执行，表明动作的状态是完成进行，前后结合，就是过去将来完成进行时态。ex:l said I would have been eating lunch for 2 hours by 1 PM tomorrow/yesterday.我)之前)说我明天/昨天下午1点前会已经吃了俩钟头中饭(我之前说我会明天/昨天下午1点时在吃中饭这个过程中,之前吃了2小时,之后还会继续吃)</p></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><hr><h2 id="动词语气-mood">动词语气(mood)</h2><p>概念：表示动作的假设，情感等。</p><p>难点：虚拟语气。</p><p><strong>语气分类</strong></p><ol><li>陈述语气：描述现实 <code>ex:The rabbit ate a carrot.</code></li><li>祈使语气：命令/请求<ol><li>用第二人称(”你”)和一般现在时态 如：<code>ex:(please)eat the carrot.</code></li><li>去掉“你”，并保持动词原形 如：<code>ex:you don't eat it=&gt;Don't eat it.</code></li></ol></li><li>虚拟语气：<ol><li>理解：人主观的意愿，往往与现实事实相反.比如“如果我知道他是这样的人，我就不会和他在一起了。”言下之意就是我不知道他是这样的人(<strong>现实事实</strong>),而假设了我知道他是这样的人(<strong>主观意愿</strong>)我会做什么。</li><li>第一大用法：虚拟语气表“不可能”假设</li></ol></li></ol><table><thead><tr><th>时间</th><th>条件句</th><th>主句</th><th>例句</th></tr></thead><tbody><tr><td>与现实相悖的想象，主观意愿</td><td>过去式)如果是be，一律改为were，不管什么人称)</td><td>Would+动词原形)注意，would可以用should、could、might替代，它们分别是shall、can、may的过去式)</td><td>If I were you,I would give this video a thumbs-up。                        if句是条件句，后面的句子就是主句)造成的结果)。</td></tr><tr><td>和过去事实相反</td><td>had+动词过去分词</td><td>Would have+动词过去分词</td><td>If I had watched this video before,I would have aced my test.</td></tr><tr><td>和将来事实相反(可能性很小)</td><td>should+动词原形(should其实是shall的过去式，也可以用were to +动词原形取代)</td><td>Would+动词原形</td><td>if I should meet thee after  long years,how should I greet thee?</td></tr></tbody></table><p>分析可得，无论是哪一种虚拟语气，他们都要使用<strong>过去式(即所在的时间前移)</strong> -如对现在假设变成过去式，对过去假设变成过去完成时。  这种过去式可能是谓语动词的过去式，也可能是will，shall和have的过去式，由此提醒：<strong>不要看见过去式就认为动作发生在过去</strong>，也有可能是虚拟的，实际并未发生的。</p><p>严格来说，should做shall的过去式时没有“应该”的含义，做情态动词的时候才有，只不过为了翻译流畅才添加含义，本来是无实际含义的。</p><ol start="3"><li>第二大用法：虚拟语气表达愿望、请求、建议、命令等(希望某个动作|事情发生)。</li><li>Wish <code>ex: I wish that I were a rabbit.</code> Would rather同理</li><li><strong>特例</strong>：demand、suggest、insist、order用虚拟语气是should+动词原形。<ol><li>suggest insist order <code>ex:I demand that you)should)give me a carrot</code></li></ol></li></ol><table><thead><tr><th>时间</th><th>句子结构</th><th>例句</th></tr></thead><tbody><tr><td>对现在的愿望</td><td>Wish+动词过去式</td><td>I wish that I were a rabbit.</td></tr><tr><td>对过去的希望</td><td>Wish+had/would have+动词过去分词</td><td>I wish (that)I had eaten the carrot.(我希望你过去吃了那个胡萝卜，言下之意就是在过去你没吃)</td></tr><tr><td>对将来的希望</td><td>Wish+should/might/could/would+动词原形</td><td>I wish (that)I could eat the carrot.</td></tr></tbody></table><p>再次强调，<strong>虚拟语气</strong>是和陈述语气并列的，所以不同于陈述语气的客观事实描述，虚拟语气描述的是非事实的，主观的，所以不能使用一般时，在翻译和写作时尤其要注意这点。</p><h2 id="非谓语动词-non-finite-verbs">非谓语动词(non-finite verbs)</h2><p>定义：谓语动词有另外的名字：限定性动词)也就是被三单、时态等限制了形式)，与之相对的就是非限定动词，也就是非谓语动词。</p><p><code>ex:I am a talking student.</code>这里的talking不被时态、人称所限制，没有动词的本领，也就是变成了非谓语动词</p><hr><p>💡谓语动词是句子的核心，也就是说，在一个简单句子中谓语动词只能有一个(在有<strong>并列关系</strong>的时候可以有多个谓语动词)，但是非谓语动词不限个数。</p><p><strong>非谓语动词分类</strong></p><h3 id="动词不定式">动词不定式</h3><p><strong>to+动词原形。表示将要发生的动作</strong></p><table><thead><tr><th>主要类型(形式)</th><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>1. 特殊情况to可以省略：make\help\let……一感二听三让四看半帮助。</td><td>不定式作主语</td><td>To eat a carrot every day is good for the rabbit.</td></tr><tr><td></td><td>不定式作直接宾语</td><td>The rabbit likes to eat carrots.</td></tr><tr><td></td><td>不定式作间接宾语</td><td>The rabbit expected the wolf to eat a carrot.强调动作已经发生(全过程)</td></tr><tr><td></td><td>不定式作宾补</td><td>The rabbit has a lot of carrots to eat.这里的to eat修饰的是carrots。</td></tr><tr><td></td><td>不定式作宾语</td><td>1. 表原因：<code>I was surprised to get a thumbs-up.</code> 2. 表目的：<code>I will do anything to get a thumbs-up.</code> 3. 表结果：<code>I got enough thumbs-up to make another video.</code></td></tr><tr><td>2. 高级不定式:to+动词原形(”状态”)</td><td>\</td><td>To be eating a carrot\To have been eating a carrot</td></tr></tbody></table><h3 id="动名词">动名词</h3><p><strong>动词原形+ing，本质是名词–主动、进行</strong></p><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>作主语</td><td>Eating carrots is healthy for the rabbit</td></tr><tr><td>作宾语</td><td>the rabbit likes eating carrots.</td></tr><tr><td>作表语</td><td>The rabbit’s hobby is growing carrots.</td></tr><tr><td>作定语</td><td>a sleeping pill 表示名词的性质、功能或者用途.等价于 a pill for sleeping</td></tr></tbody></table><p>需要注意的是，虽然理论上任何动词不定式和动名词可以充当另一个动词的宾语，但是实际上不是，如enjoy不能用不定式充当宾语等。同样，也有些动词不能直接接动名词，而是要借助介词，比如  <code>ex:The rabbit is looking forward to eating carrots</code> 这里的to是介词而不是不定式的to。</p><h3 id="固定搭配">固定搭配</h3><p><strong>不定式与动名词的使用范围</strong></p><ol><li>如stop to do/doing,forget to do/doing,remenber to do/doing……，前者指怎样(停止、记得……)去做某事)还没做)，后者指怎样去做某事)已经做了)</li><li>感到用ed，令人ing.如interested与interesting</li></ol><h3 id="现在分词">现在分词</h3><p><strong>本质是形容词–主动、进行</strong></p><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>作表语</td><td>the rabbit is charming  很多的形容词实际上就是现在分词</td></tr><tr><td>作宾补</td><td>The wolf saw the rabbit eating a carrot.强调动作进行的状态。即狼看到兔子正在吃</td></tr><tr><td>作状语</td><td>Not knowing what to eat,the rabbit skipped lunch. 可以表示原因、时间、伴随等关系</td></tr><tr><td>作定语</td><td>a sleeping rabbit. 表明兔子的状态是睡觉，但是不同于动名词作定语。</td></tr></tbody></table><h3 id="过去分词">过去分词</h3><p><strong>暗含被动关系，不表示过去时间</strong></p><table><thead><tr><th style="text-align:left">形式</th><th>例子</th></tr></thead><tbody><tr><td style="text-align:left">作<strong>后置定语</strong></td><td>The carrot cake eaten by the rabbit is delicious</td></tr><tr><td style="text-align:left">作表语</td><td>The rabbit is interested in growing carrots.</td></tr><tr><td style="text-align:left">作宾补</td><td>The rabbit found his carrot stolen.</td></tr><tr><td style="text-align:left">作状语</td><td>1. 表地点：Seen from the hill,the carrot field looks beautiful.  2. 表原因：Born in a rabbit family,the rabbit has been growing carrots all his life. 3. 表条件：Given another chance,the rabbit would go to the wolf’s party.`</td></tr></tbody></table><p>判断谓语使用现在分词还是过去分词，看主语是主动还是被动完成动作。<code>ex:seen from the hill,the carrot field looks beautiful</code> 田地是“被看&quot;，所以使用过去分词</p><hr><p>特例：独立主格：ex:The work finished,the rabbit went home.这里went是谓语动词，finished是非谓语动词(过去分词)，修饰work.</p><hr><h3 id="扩展：独立主格">扩展：独立主格</h3><p>我们来看下这个句子<code>because he was invited by the wolf,the rabbit decided to go to the party.</code> 如果用过去分词来表示(因为这里表原因而且是被动)，则变为<code>Invited by the wolf,the rabbit decided to go to the party</code>。</p><p>但如果是主动关系呢？</p><p>我们来看一下这个句子<code>because the wolf invited him,the rabbit decided to go to the party.</code> 这是一个完整的句子，如果我们要将前面的句子简化。则改为<code>The wolf inviting him,the rabbit decided to go to the party.</code><br>The rabbit句子是句子的主干，前面句子表示原因，invite这个动作由the wolf发出，所以是主动关系-使用现在分词。The wolf是前面句子的逻辑主语，也就是独立主语后面不能用动词原形。</p><p>独立主格的结构：名词|代词+be动词的现在分词being，然后再把being省掉。<br>例如：<code>The rabbit came in,carrot (being) in hand</code><br>特殊独立主格：with+宾语+宾语补足语<br><code>With the work finished,the rabbit went home.</code> ⇒ the work finished,the rabbit went home.</p><p>由此可得，<u>独立主格是和非谓语结构紧密相连的，更像是非谓语动词省去be的简化形式</u>，不过省略的前提是存在逻辑主格。</p><h2 id="助动词">助动词</h2><p>定义：辅助动词构成谓语但是本身“不能“作谓语动词的词就是助动词。</p><blockquote><p>这里的“不能”不是说助动词不能作动词，助动词作实义动词时可以作谓语动词，比如do，be等.</p></blockquote><p><code>ex:the rabbit will eat a rabbit.</code> 谓语动词本身无法表达“将来”的时间，所以需要借助will来构成“将来时”。</p><p>在很多语法书中将情态动词与助动词单独分类，但实际上<strong>情态动词也是起辅助作用，“不能”单独做谓语动词</strong>，所以本质上情态动词还是助动词。这里我就将两者作为一类</p><h3 id="助动词分类">助动词分类</h3><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">1.基本</button><button type="button" class="tab">2.情态动词</button><button type="button" class="tab">3.半助动词</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>be、do、have</strong></p></div><div class="tab-item-content"><ol><li><p>can/could：</p><ol><li><p>前者是有能力，后者是过去有能力，现在有没有不知道 <code>ex:I can  kill a wolf</code></p></li><li><p>前后都可以表示请求、许可，后者更加委婉。 <code>ex:Could i borrow your book?</code></p></li><li><p>前后都表示可能性，后者表示对过去的推测/现在的可能性  <code>ex:Angthing can happen.</code></p></li></ol></li><li><p>may/might：</p><ol><li>表示请求或者许可，后者更礼貌  <code>ex:May I borrow your book?</code></li><li>表示可能性，后者的可能性更小 <code>ex:He may be at home.</code></li><li>表示祝愿 <code>ex:May you succeed!</code> 这种情况不使用might</li></ol></li><li><p>must</p><ol><li>表示必须  <code>ex:you must do your homework.</code></li><li>表示禁止must not 意思是必须不、绝对不，否定的意思更强烈  <code>ex:you must not smoke here</code></li><li>表示推测，而且是肯定的推测  <code>ex:The light is on.The rabbit must be at home.</code></li></ol></li><li><p>will/would：</p><ol><li>构成将来时 <code>ex:I will have breakfast.</code></li><li>表示请求，后者更加委婉 <code>ex:Would you give me a cup of coffee?</code></li><li>表推测，假设，后者的不确定性更大建议 <code>ex:Ask him,He will konw.</code></li></ol></li><li><p>shall/should：</p><ol><li>shall可以构成将来时  <code>ex:I shall be there at 9AM.</code></li><li>shall表示请求或者征求意见  <code>ex:Shall we go to the movie?</code></li><li>表示警告，命令  <code>ex:You shall not pass!</code></li><li>should表示应当</li><li>should表示有一定根据的推测  <code>ex:It should rain tomorrow.</code></li><li>should表示“竟然”   <code>ex:It's surprising that he should be late.</code></li><li>虚拟语气  <code>ex:If it should rain tomorrow,I wouldn't go.</code></li></ol></li><li><p>ought to：应该，语气比should更强烈  <code>ex:We ought to finish it first.</code></p></li><li><p>dare/dared ：</p><ol><li>实意动词：敢，冒险</li><li>情态动词：敢   <code>ex:How dare you.</code></li></ol></li><li><p>need：</p><ol><li>需要</li><li>既可以作实义动词，也可以作情态动词 <code>ex:Students need study.</code> == <code>ex:Student need to study.</code>  前面的need是情态动词，后面的是实义动词</li></ol></li><li><p>used to：表过去的动作，往往是习惯或者是重复的动作，</p></li></ol></div><div class="tab-item-content"><table><thead><tr><th>形式</th><th>含义</th><th>例子</th></tr></thead><tbody><tr><td>be able to</td><td>表示能力，可以表示将来的能力|特别注意的是，was/were able to 表示成功做成</td><td>I’ll be able to reach school on time|I was able to reach school on time because I left home early.</td></tr><tr><td>be going to|be about to|be to</td><td>表示将要做某事，第一个表示计划做某事，第二个是马上做某事，第三个是被命令做某事</td><td>I am going to eat dinner at 6 PM today.</td></tr><tr><td>had better</td><td>最好做，缩写是’d better</td><td>you’d better listen to me.</td></tr></tbody></table></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><h2 id="系动词">系动词</h2><p>定义：相当于C语言中的赋值符号=，将后者赋予前者</p><p>如：I am a rabbit 就是将rabbit赋予给我，即我=rabbit。某某起来的系动词(<code>ex:he looks handsome</code>)与此相同，只不过在翻译的时候增加了系动词的意思。</p><h2 id="使役动词">使役动词</h2><p>定义：意思是使、让、令的词语，语法结构：使役动词+宾语+宾语补足语</p><p><strong>常见的使役动词</strong></p><ol><li>make：<ol><li>make+动词原形(其实是省去 to的不定式)： <code>ex:Employer make his employee work once again.</code></li><li>形容词 如：<code>the cattot made the wolf full</code></li></ol></li><li>let：允许某人做某事(不绝对)let+动词原形(其实是省去 to的不定式) <code>ex:I'll let the wolf eat some chocolate.</code> |副词  <code>ex:let me out.</code></li><li>have：have +动词原形(给某人、物/责任做) 如：<code>I will have the wolf wash the dishes</code>  | have + 动词过去分词 表示让某人做某事</li><li>get：get +不定式(说服/鼓励……做……)  <code>I'll get the wolf to clean the kitchen.</code>|get +过去分词    <code>ex:I got my nails done.</code></li></ol><h1>从句</h1><p>举个例子，我看见兔子吃了胡萝卜，这里主语是“我”，谓语动词是”看见“，那宾语是什么？是”兔子吃了胡萝卜“这件事，这件事本身单独看是完整的句子，<strong>这种充当句子成分的句子就叫做从句</strong>。英语为 <code>ex:I saw that the rabbit ate a carrot.</code> 这里I saw 为主句，that及其之后的是从句。</p><p>句子分类</p><ol><li>简单句：不可再拆</li><li>复合句：不分主次，也就是并列。</li><li>复杂句：主句+从句</li></ol><p>在句子中，每一个句子成分都可以由句子充当，比如主语被句子充当就变成主句从句。分成三大类就是名词从句、形容词从句、副词从句。</p><p><strong>如何理解中式造句与英式造句之间的差异？<strong>比如这句话“一根我买来的胡萝卜”，在中文中用形容词(定语)+名词的方式，无论定语有多长，而在英语中是在在被修饰的词之后(<strong>先行词)</strong>+与他有关系的词(<strong>关系词</strong>)+句子补充说明，这里就是 <code>ex:a carrot that I bought.</code>  即</strong>中文中定语都是前置的，而英语中定语大部分都是后置的</strong>。也就是说，在用英语造句的时候，可以先将对应的中文拆句，比如“一只几个月前开始在B站上传视频专门教英语的讨人喜爱的兔子”，核心主干是“<strong>一只兔子</strong>”，而“几个月前”“开始在B站上传视频”“专门教英语的”“讨人喜爱的”全都是定语，可以将其放在关系词后面，再按照一定的顺序进行调整。</p><h2 id="关系词">关系词</h2><h3 id="分类">分类</h3><ol><li>关系代词：代指前面的部分 <code>ex:The rabbit is eating a carrot that I bought.</code> 可以看到，后面的句子作陈述句的时候是<code>ex:I bought a carrot.</code>,然后用that 代指 a carrot ,再将关系代词提前，则变为<code>ex:that I bought.</code> 常见的还有who\whom\which\whose .<ol><li>that与which的区别:  当先行词是唯一的时候使用that，而先行词多选一的时候使用which. <code>ex:the only rabbit that ate a carrot.</code>  <code>ex:The rabbit ate a carrot which I bought.</code> 言下之意就是这里有多个胡萝卜，但这个兔子只吃了我买的那个。</li></ol></li><li>关系副词: 前面的部分在从句中充当副词 <code>ex:This was the place where the rabbit ate the carrot.</code> 当然也可以用关系代词替代，<code>ex:This was the place at which the rabbit ate the carrot.</code> 由此可得，关系副词=介词+which</li></ol><h2 id="形容词性从句">形容词性从句</h2><h3 id="限定性形容词从句与非限定形容词从句">限定性形容词从句与非限定形容词从句</h3><p><code>ex:The rabbit is eating a carrot that I bought.</code> 这里that句限定了carrot的范围/性质 而<code>ex:The rabbit ate the carrot,which was on the table.</code> 这里的which更多起到代词的作用，并没有限定的作用。</p><h3 id="分类-v2">分类</h3><ol><li>非限定性形容词从句作插入语  <code>ex:My head,which is big,is useful when it rains.</code></li><li>非限定性形容词从句指代整句话  <code>ex:The rabbit ate the carrot,which was not surprising.</code> 这里的which指代The rabbit ate the carrot.</li></ol><h2 id="名词性从句">名词性从句</h2><h3 id="1-主语从句">1. 主语从句</h3><p>主语由从句充当 <code>ex:That the rabbit ate a carrot is obvious.</code> 引导词还可以用who/where/when/how/what等<strong>主语从句要以引导词作为开头</strong>。</p><ul><li><p>形式主语</p><p><code>ex:It is obvious that the rabbit ate a carrot.</code> 这里It作为形式主语，而真正的主语是that句。</p></li></ul><h3 id="2-宾语从句">2. 宾语从句</h3><ol><li>确定信息与不确定信息 <code>ex:I saw that the rabbit ate a carrot.</code> <code>ex:I saw whether the rabbit ate the carrot.</code></li><li>that省略：<code>ex:I know (that)the rabbit ate a carrot.</code>  如果that省略之后有歧义则不能省略。</li><li>某些词后的宾语从句的否定：否定加在谓语动词前，而非从句中。<code>ex:I don't think (that) the rabbit is smart.</code> 而不是isn’t</li><li><strong>主从时态一致</strong>：<code>ex:I don't think (that)you're right.</code> 除非是不变的客观现象(比如the sun rises in the east.)</li><li>特殊：be+形容词+that. <code>ex:I am sure that there's a carrot on the table.</code></li></ol><h3 id="3-表语从句">3. 表语从句</h3><ol><li>系动词为be ：<code>ex:The problem is that the rabbit is hungry.</code></li><li>系动词为非be动词：<code>ex:It seems that the rabbit is hungry.</code></li></ol><h3 id="4-同位语从句">4. 同位语从句</h3><p>同位语简单来说就是名词的另一种说法。<code>ex:My teacher,Papa Rabbit,likes carrots.</code> 这里的Papa Rabbit实际上指的还是My teacher.</p><p><code>ex:The fact that the rabbit ate the carrot did not surprise me.</code></p><h3 id="5-宾语补语从句">5. 宾语补语从句</h3><p><code>ex:My education made me who I am today.</code></p><h2 id="副词从句">副词从句</h2><p>副词从句充当句子中状语的部分，所以也成为状语从句</p><h3 id="分类-v3">分类</h3><ol><li><p>表时间</p><table><thead><tr><th>含义</th><th>引导词</th><th>例子</th></tr></thead><tbody><tr><td>在…前</td><td>before</td><td>The rabbit ate a carrot at home before the wolf stopped by. The到before之前是主句，the wolf到by是从句。如果要将从句提前需要断句Before the wolf stopped by,the rabbit ate a carrot at home.</td></tr><tr><td>在……时</td><td>when\while\as。when表示突然，while表示时间段，as表示同时</td><td>I ate a carrot as I made the video.</td></tr><tr><td>在……之后</td><td>after</td><td>The rabbit ate a carrot after the wolf stopped by.</td></tr><tr><td>从之前某一段时间点开始算</td><td>since</td><td>The rabbit has shared three carrots since the wolf stopped by.</td></tr><tr><td>直到之后的某一时间点</td><td>until</td><td>The student waited until the bus came.</td></tr><tr><td>一……就……</td><td>as soon as</td><td>The rabbit will eat a carrot as soon as the wolf leaves.</td></tr><tr><td>下次</td><td>the next time</td><td>The rabbit will share the biggest carrot the next time the wolf stops by.</td></tr></tbody></table></li><li><p>表地点(如：在…地方) 引导词：where+“强调形式”(wherever,anywhere……) <code>ex:The rabbit will go wherever he can find a carrot.</code></p></li><li><p>表条件(如：如果…) <code>ex:If the rabbit sees a carrot,he will eat it.</code> 遵循“主将从现” ，从句(if引导的句子)的假设是不确定的，不能用will，所以用一般现在时态，而一旦假设成立，那么一定某件事发生，这种确定的发生用一般将来时态。<strong>即条件句比主句落后一个时间段</strong>。其他的引导词如unless,provided,as long as,in case 等</p></li><li><p>表让步(如：虽然…但是…) <code>ex:Even if I see a carrot,I will not eat it.</code> 同样的还是有thought\although\no matter</p></li><li><p>表方式(如：就好像…)  <code>ex:I feel good as if I had just eaten a carrot.</code></p></li><li><p>表比较(如：比…) <code>ex:He is smarter than I (am).</code> 其实就等效于口语化的 <code>ex:He is smarter than me.</code> 同样比较的词有as……as,the more…… the more.</p></li><li><p>表原因(如：因为所以…) <code>ex:The rabbit ate the carrot because he was hungry.</code> 不能用because和so搭配是因为because用来构成复杂句，so用来构成复合句，两者混用会导致句子结构混乱，同理还有though和but.同样的词还有since\as，不过这两个词构成的副词从句一般放在主句前。</p></li><li><p>表目的)如：为了…) <code>ex:In order that I could finish the video in time,I pulled an all-nighter.</code> 同样的词还有so that。so that既能表示目的也能表示结果，在翻译的时候要注意这一点。</p></li><li><p>表结果(如：所以…)  <code>ex:I ate a lot of carrots for lunch so that I wasn't hungry at all in the afternoon.</code> 同样的词还有so,such that,such后面要接名词。</p></li></ol><h1>非动词</h1><h2 id="冠词">冠词</h2><p>分类如下</p><div class="tabs"><div class="nav-tabs"><button type="button" class="tab active">1.不定冠词</button><button type="button" class="tab">2.定冠词</button><button type="button" class="tab">3.零冠词</button></div><div class="tab-contents"><div class="tab-item-content active"><p><strong>使用范围：判断音素(即首音标而不是字母)发音是元音还是辅音 如 a university/an hour</strong></p><p><strong>意思分类如下</strong></p><table><thead><tr><th>含义</th><th>例子</th></tr></thead><tbody><tr><td>泛指</td><td>I saw a rabbit.(我看到只兔子-指某一只)</td></tr><tr><td>某一类)看语境去理解)</td><td>最好是用相关名词的复数 A rabbit is smarter than a wolf. 这里的意思是兔子比狼聪明</td></tr><tr><td>表示数字1</td><td>I gave you a hundred carrots.</td></tr><tr><td>表示每</td><td>I give you a hundred carrots a day.</td></tr><tr><td>主谓一致</td><td>a teacher and video creator.这里老师和创作者都是指同一个人。如果是a teacher and a video creator. 这里指的是两个人。</td></tr><tr><td>固定搭配</td><td>as a result\have a good time……</td></tr></tbody></table></div><div class="tab-item-content"><p><em><strong>The</strong></em></p><ol><li><p>发音</p><ol><li>两个发音：在辅音音素前读[ðə]比如：the book 那书，the desk 那桌子，the table 那桌子。</li><li>在元音音素前读[ði]。比如：the apple 那苹果，the ant 那蚂蚁，the elephant 那大象。</li></ol></li><li><p>意思</p><table><thead><tr><th>作用</th><th>例子</th></tr></thead><tbody><tr><td><strong>特指</strong></td><td>The school</td></tr><tr><td>再次提到的人或者事物</td><td>I saw a rabbit.The rabbit ran fast.</td></tr><tr><td>用在序数词和形容词的最高级前(某种意义上也是特指)</td><td>The first rabbit.</td></tr><tr><td>独一无二的名词</td><td>The sun,the Great Wall.</td></tr><tr><td>泛指</td><td>play the piano. 如果这里the用a则侧重强调弹钢琴的动作。</td></tr><tr><td>固定表达</td><td>all the time.</td></tr><tr><td>The +adj表示一类人</td><td>the rich should help the poor.</td></tr></tbody></table></li></ol></div><div class="tab-item-content"><ol><li>复数泛指  <code>ex:Rabbits are smart.</code> 这样更好体现某一类事物</li><li>表示概念  <code>ex:Summer is hot.Winter is cold.</code> 这里表达的是“夏季”这一季节概念</li><li>专有名词 <code>ex:Washington DC.</code></li><li>固定表达：如play +球类/棋类/非西洋乐器 play+the+西洋乐器</li></ol></div></div><div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div><hr><h2 id="介词">介词</h2><p><strong>概念</strong>：本意是前置词prepositon ,补充信息的作用。</p><h3 id="常见介词分类">常见介词分类</h3><ol><li>简单介词：in\on\with…… 分别具有<strong>多重含义</strong>，所以翻译会与中文不同，所以<u>不要想着找到所有意思的中文与之对应，最好在语境中去理解与记忆。</u></li><li>短语介词：According to……</li><li>合成介词：into……</li><li>分词介词：provided\including……</li></ol><h3 id="介词的本源与引申">介词的本源与引申</h3><ol><li>About——on the outside of 在 的外面——引申为关于、大约、针对、具有某种特性、到处。<code>ex:There are about 2 carrots.</code></li><li>on——在 之上：有一面确定，所以是较小的范围)“相对的”)<code>ex:Dinner is on me.</code></li><li>beyond——在 之外：<code>ex:It's beyond me.</code></li><li>in——在 之内：一般是在一堆东西之间，大范围  <code>ex:dressed in white.In English.</code></li><li>At:在一个“点”上.<code>ex:At the corner.At shop.</code></li><li>区别：从in到at范围(可以是时间也可以是空间)逐渐变小，<u>但这个范围是相对的</u></li></ol><table><thead><tr><th>区别</th><th>例子</th></tr></thead><tbody><tr><td>in一般表示在某某之中，也就是说明在一个大范围之内/但morning比day小为什么能用in？因为这里morning表达的是时间段，相对的”大范围“，所以使用in。</td><td>in a year\month\week。</td></tr><tr><td>on表示在……之上，有一面确定，所以是较小的范围</td><td>on that day</td></tr><tr><td>at在一个“点”上,这个点是抽象的点，可以是时间的点也可以是地点的点。</td><td>at 8 o’clock</td></tr><tr><td>应用含义不同。</td><td>Walking in the street.表达在整条街道上移动。Some trash on the street表达街道表面有垃圾。I am at C street and B street. 表达在两条街道的交界带。</td></tr></tbody></table><h3 id="常见介词的用法">常见介词的用法</h3><ol><li>in：在内部 <code>ex:In the country.</code> 以……方式</li><li>on：在上面、与物体有接触 <code>ex:on the table.</code>   <code>ex:we talked on the phone.</code></li><li>at：在某处  <code>ex:at bus station.</code></li><li>over:在……上方(可以接触，可以不接触)、覆盖、越过上空|有动态   <code>ex:The plane flew over the mountain.</code></li><li>above：在……上方(高于平面)</li></ol><h3 id="常用其他介词">常用其他介词</h3><table><thead><tr><th>形式</th><th>含义</th><th>例子</th></tr></thead><tbody><tr><td>under</td><td>在……下方，与over相对，一般在正下方</td><td>under the tree</td></tr><tr><td>below</td><td>与above相对</td><td>The rabbit dived below the surface of the water.</td></tr><tr><td>near</td><td>在……周边</td><td>The school is near the hospital</td></tr><tr><td>by/beside</td><td>在……旁边：——引申为不超过 边界/不迟于 前</td><td>There is a hotel by/beside the river.</td></tr><tr><td>next to</td><td>靠近，紧挨着</td><td>The rabbit sat next to the wolf.</td></tr><tr><td>across</td><td>(从表面)穿过</td><td>Walk across the sidewalk</td></tr><tr><td>through</td><td>(从内部)穿过/通过某种方式</td><td>go through the tunnel.</td></tr><tr><td>past</td><td>经过，路过</td><td>Passing through a small area</td></tr><tr><td>in front of/in the front of</td><td>在……的前面，后者是在内部的前面</td><td>The driver is at the front of the car</td></tr><tr><td>before</td><td>在……之前</td><td>Someone has been here before me</td></tr><tr><td>between……and</td><td>两者之间</td><td>Between the father and the mother are their children</td></tr><tr><td>among</td><td>三者之间或三者以上</td><td>He divided the country among his sons</td></tr><tr><td>round/around</td><td>环绕</td><td>trees around the field.</td></tr><tr><td>along</td><td>沿着</td><td>we walk along the beach</td></tr><tr><td>to</td><td>朝着</td><td>we are going to town on the bus,okay?</td></tr><tr><td>toward/towards</td><td>朝着……的方向</td><td>walk toward home.</td></tr><tr><td>onto</td><td>到……上面</td><td>the rabbit jumped onto the table.</td></tr><tr><td>into</td><td>到……里面</td><td>let’s go into the garden</td></tr><tr><td>out of</td><td>从里面出来</td><td>an apple rolled out of the bag</td></tr><tr><td>opposite</td><td>在……对面</td><td>our school is opposite my house.</td></tr><tr><td>against</td><td>与……相反；倚靠</td><td>The rabbit was leaning against the tree.</td></tr><tr><td>up</td><td>沿……向上</td><td>put those books up on the top shelf</td></tr><tr><td>down</td><td>沿……向下</td><td>Is this lift going down</td></tr><tr><td>off</td><td>离……有一定距离</td><td>New Zealand lies off the eastern coast of Australia.</td></tr><tr><td>until</td><td>直到</td><td>we did not eat until past midnight</td></tr><tr><td>during</td><td>持续；在……期间</td><td>during the past 2 days.</td></tr><tr><td>for</td><td>因为 ；因 持续；以 价钱</td><td>I bought these books for 100 Yuan.</td></tr><tr><td>since</td><td>自从</td><td>I’ve long since forgotten anything I ever learned</td></tr><tr><td>from to</td><td>从……到……</td><td>from 9:00 to 10:00.</td></tr><tr><td>by</td><td>通过/后接度量标准</td><td>I go to school by car. /They get paid by the hour.</td></tr><tr><td>with</td><td>用 ；和 一起；……的原因是</td><td>The rabbit is shaking with cold.</td></tr><tr><td>because/because of</td><td>前接从句后接名词/同样后接名词的还有Due to/owing to/on account of</td><td>The rabbit didn’t go out because of the rain.</td></tr><tr><td>of</td><td>此外的、附加的</td><td>He thought of something important.</td></tr><tr><td>besides</td><td>除了……还</td><td>I like many things besides carrots.</td></tr><tr><td>except</td><td>除了</td><td>Everyone went to the party except the rabbit.</td></tr><tr><td>except for</td><td>往往用来对之间的内容进行反驳</td><td>The party is great except for the loud music.</td></tr><tr><td>……</td><td>……</td><td>……</td></tr></tbody></table><p>💡尽可能由本源引申扩展义，在具体的语境中理解和记忆，不需要死记。</p><h3 id="介词短语">介词短语</h3><p>由介词+宾语组成的短语，可以充当句子成分</p><ol><li>Between 10 and 11 is a good time for me. 作主语</li><li>The meeting is at 2 o’clock.作表语</li><li>This is the key to the house.作定语</li><li>……</li></ol><h3 id="短语动词">短语动词</h3><p>由动词+介词构成一个新的动词。比如check out ,make out……。大多数是固定搭配需要记忆。</p><hr><h2 id="名词">名词</h2><h3 id="名词的分类">名词的分类</h3><ol><li>普通名词与专有名词(首字母大写)：如人名Mike，国家China</li><li>由单数和复数分：可数名词与不可数名词<ol><li>如集合名词：team,可以作单数也可以作复数，不过意思分别为团队、队伍，也就是集合名词的含义会随着单复数而变化。</li><li>抽象概念不可数：比如和平peace，诚实honesty</li><li>数不清的名词：water 大多数情况下为不可数名词，但是也有例外，如 two waters 意思是两片水域。</li><li>专有名词的复数：如Mikes,有时候代表几个加Mike的的人，或者是指Mike一家。</li></ol></li></ol><p>💡<strong>名词的单复数不在于名词本身，而是在于名词在不同的语境中要表达什么意思</strong>，然后选择是单数还是复数。如 a glass of water 可数的是杯子而不是水，所以表达复数是two glasses of water.</p><h3 id="名词的所有格">名词的所有格</h3><ol><li>‘s:表示从属关系，如Mike’s hand 。如果其主格是复数就打’即可。比如parents’ kids.<ol><li>表示修饰、特性：</li><li>并列<strong>共有</strong>的情况下最后一个加所有格：Tom and Jerry’s room</li></ol></li><li>of:a room of school⇒the school’s room</li><li>双重所有格：I am a friend of Mike’s.用Mike’s修饰friend.即Mike的朋友有很多，我只是他其中的一个。</li></ol><h2 id="代词">代词</h2><p>定义：就是用一个词代替之前说过的词，更多是用于简化和避免重复。</p><h3 id="分类-v4">分类</h3><ol><li>人称代词：<ol><li>人称代词的“格”：主格或者宾格，即代词在不同的格会有不同的变化。注意 <code>ex:you and I.</code>等<strong>一般习惯把对方放前面，“我”放在后面</strong></li><li>人称代词的表格搜一下就能找到，不过比较简单。</li><li>物主代词： my(形容词性物主代词) mine(名词性物主代词)<code>ex:It is my carrot.The carrot is mine.</code> 形容词性物主代词充当了形容词，而名词性物主代词充当了名词。</li><li>反身代词：<code>ex:I saw myself.</code></li><li>强调代词：the rabbit washed the carrots himself(himself作状语)</li></ol></li><li>相互代词：<code>ex:we should help each other.</code>(扩：one another 三者之间|三者以上之间)</li><li>指示代词：this these……这，这些——指代离说话人较近的事物|that those……那、那些——指代离说话人较远的事物</li><li>不定代词：<table><thead><tr><th>不定代词</th><th>区别</th></tr></thead><tbody><tr><td>Many\much</td><td>前者修饰可数名词，后者修饰不可数名词</td></tr><tr><td>A few\few\a little\little</td><td>few接可数名词，little接不可数名词；不加a 表示很少，有否定意义.</td></tr><tr><td>Some\any</td><td>前者常用于肯定句，后者常用于否定句；any表示任意一个可以用在肯定句中.Does the rabbit need any carrots?</td></tr><tr><td>Each\every</td><td>前者可以单独做主语；each用于两个、两个以上，every用于三个、三个以上.each carrot\every carrot There are many carrots on each side of the street.</td></tr><tr><td>Either\neither</td><td>谓语动词用单数 Either of books is OK.</td></tr><tr><td>Both\all</td><td>前者是两者都，后者是三者及以上都  All of the rabbits are cute.</td></tr><tr><td>Other\the other\another</td><td>第一个表示另外的(+名词)，第二个特指两者中的另外一个，another表示三个或以上另一个.This carrot is bigger than the other carrot.\The rabbit doesn’t like this carrot.\Give him another carrot.</td></tr><tr><td>One\it</td><td>One指同一类事物，it指上下文“同一个事物”</td></tr></tbody></table></li><li>复合不定代词：every-，some-，any-，no-.形容词在修饰复合不定代词时后置。<code>ex:The rabbit has something important to do.</code></li><li>疑问代词：whom who…… <code>ex:Who killed him?</code></li><li>连接代词：whom,whichever,what whatever,whoever……在从句中就变成连接代词  <code>ex:From whom did the rabbit get the carrots?</code> <code>ex:What he said isn't true.</code></li><li>关系代词：who\whom\whose\which\that\as:<code>ex:The rabbit whose ears are long ate a carrot.</code></li></ol><hr><h2 id="数词">数词</h2><p>分为基数词和序数词</p><h3 id="基数">基数</h3><ol><li>1-10：不解释，已经刻在DNA里面了 11-eleven 12-twelve 13-thirteen 14: +teen(后缀) 20、30……: twen +ty(后缀)</li><li>几十+几：twenty-one</li><li>百：two hundred ,余数用and连接：three hunred and five(305)</li><li>千、万、亿：two thousand|three thousand five hunred and twenty-one(3521)</li><li>扩展：三位数划分法：1，000,000,000中间的空格分别是十亿、百万、千(billion million thousand)，西方人按照这样的顺序读数字  <code>ex:four hundred and seventy-eight billion eight hundred and seventy-three million four hundred and sixty-seven thousand eight hundred and twenty-three</code> 478,873,467,823。</li><li>用法：<ol><li>固定搭配：hundreds\thousands\millions of 成……上…… 本意都是<strong>特别多</strong></li><li>充当句子成分：<code>ex:It costs fifty.</code> 充当宾语；<code>ex:you two.</code> two为同位语。</li></ol></li></ol><h3 id="序数词">序数词</h3><p>一般的基数词+th 20----90(整十数)：基数词把y改写为ie+th。如thirtieth<br>缩写：阿拉伯数字+st|nd|rd.<br>对于任意一个序数词，整十整百位基数词，个位变序数词，如<code>ex:twenty-second.</code> 如果序数词充当句子成分，一般要在前面+the。</p><ol><li><p>分数：One third 三分之一 a quarter 四分之一 two and one third 2的三分之一次方</p></li><li><p>小数：one point three four 1.34，加了point就是小数,左边就是实数部分，右边就是小数部分。</p></li><li><p>百分数：……+percent  <code>ex:two point five percent.</code></p></li><li><p>倍数：</p><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>倍数+the+计量+of</td><td>This carrot is half/twice/three times the size of that one.</td></tr><tr><td>倍数+as……as……</td><td>I have half/twice/three times as many carrots as he has.</td></tr><tr><td>倍数+比较级+than</td><td>I can eat three times faster than he can.</td></tr><tr><td>by+倍数</td><td>I have increased my income by three times.</td></tr></tbody></table></li><li><p>算术：2 plus 2 is 4:加法|4 minus 2 is 2:减法|2 multiplied by/times 3 is 6：乘法|8 divided by 4 is 2：除法|squared：平方|cubed:立方|more than：大于</p></li><li><p>单位：时间：<code>ex:at seven(7:00) a quarter past seven(7:15) half past seven(7:30) ten to eight(7:50).</code></p></li><li><p>年份：美式：月|日|年    <code>ex:December 12th,2020.</code>  BC 公元前  <code>ex:500 B.C.</code>  AD公元 2020’s|2020s 二十一世纪20年代</p></li><li><p>度量表示：</p><ol><li>基数词+单位词(复数)+形容词(长宽高):<code>ex:The river is 1000 meters long.</code></li><li>基数词+单位词(复数)+in+(长宽高)名词:  <code>ex:The river is 1000 meters in length.</code></li><li>面积和体积：<code>ex:This room is 700 square meters.</code> 这个房间有700平方米。</li><li>……</li></ol></li></ol><hr><h2 id="形容词">形容词</h2><h3 id="定语用法">定语用法</h3><ol><li>前置定语：<code>a hungry rabbit</code>形容词的顺序：限定词(冠词，物主代词等) +(主观)特征+尺寸+形状+新旧+颜色+来源+材料+用途 如：<code>a beautiful big round new black Chinese wooden table</code> 口诀是 <strong>美小圆旧黄，中国木书房</strong></li><li>后置定语：常用于修饰复合不定代词：<code>everything possible</code></li><li>形容词短语作定语：<code>the rabbit eager to eat carrots</code></li><li>表语：<code>ex:The rabbit is hungry.</code> 有些只能作表语，如asleep,alive……</li><li>Alive|asleep|alone等以a开头的形容词:一般只做表语，<code>The rabbit is alive/asleep/alone</code></li><li>表示身体状况的形容词一般如ill、will一般只能作表语而不作前置定语 如<code>The rabbit is ill/well.</code></li><li>补语：如make+宾语+宾补 <code>ex:carrots make rabbits happy.</code></li><li>状语：<code>The rabbit came home,tired and hungry.</code></li></ol><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>前置定语</td><td>a hungry rabbit形容词的顺序：限定词(冠词，物主代词等) +(主观)特征+尺寸+形状+新旧+颜色+来源+材料+用途 如：a beautiful big round new black Chinese wooden table <em>美小圆旧黄，中国木书房</em></td></tr><tr><td>后置定语，常用于修饰复合不定代词</td><td>everything possible</td></tr><tr><td>形容词短语作定语</td><td>the rabbit eager to eat carrots</td></tr><tr><td>表语</td><td>The rabbit is hungry. 有些只能作表语，如asleep,alive……</td></tr><tr><td>Alive\asleep\alone等以a开头的形容词一般只做表语</td><td>The rabbit is alive/asleep/alone</td></tr><tr><td>表示身体状况的形容词一般如ill、will一般只能作表语而不作前置定语</td><td>The rabbit is ill/well.</td></tr><tr><td>补语：如make+宾语+宾补</td><td>carrots make rabbits happy.</td></tr><tr><td>状语</td><td>The rabbit came home,tired and hungry.</td></tr></tbody></table><h3 id="形容词的构成">形容词的构成</h3><p>很多中间带有“-”往往就是这样的合成词，这样的合成词大多构成形容词。个人感觉能用从句就不用这种合成构词，避免犯错。</p><ol><li>形容词+形容词/现在分词/过去分词：<code>a red-hot coal</code></li><li>副词+形容词/现在分词/过去分词:<code>hard-working</code></li><li>形容词/数词+名词:<code>kind-hearted</code> 等效于<code>ex:a man whose heart is kind.</code></li><li>名词+形容词/现在分词/过去分词:<code>a snow-white rabbit</code></li></ol><h3 id="比较级与最高级">比较级与最高级</h3><table><thead><tr><th>含义</th><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>一般类</td><td>单词末尾+er|+est，有些特殊的要改写y为i再+er\est.</td><td></td></tr><tr><td>特殊类</td><td>重读闭音节：双写辅音字母+er\est.多音节和部分双音节词前面加上more\most；不规则变化：记！</td><td>bigger\more beautiful</td></tr><tr><td>比……更</td><td>(倍数)+比较级+than</td><td>This carrot is three times bigger than that one.three times 表示的是倍数，后面的比较级+than才是主要结构。</td></tr><tr><td>和……一样</td><td>as ……as</td><td>This carrot is three times as big as that one.</td></tr><tr><td>越来越</td><td>比较级+and+比较级</td><td>faster and faster. \more and more beautiful.</td></tr><tr><td>越……，就越……</td><td>the+比较级(原因)+补充内容，the+比较级(结果)+补充内容</td><td>The more carrots the rabbit eats,the smarter he will become.</td></tr><tr><td>最高级</td><td>最高级一般前面+the</td><td>Magic mirror on the wall,who is the fairest one of all?</td></tr></tbody></table><hr><h2 id="副词">副词</h2><p>adj+adv：pretty|fast   大多数副词都是在形容词后面+ly，少部分去e+ly。注意有些词变为副词后词义改变较大。如largely.</p><h3 id="副词的修饰作用">副词的修饰作用</h3><ol><li>副词修饰动词：<code>ex:this rabbit runs fast</code></li><li>副词修饰形容词和副词：<code>ex:this rabbit runs very fast;I am doning very well</code></li><li>副词修饰名词：<code>ex:this rabbit here runs very fast.</code></li><li>副词修饰句子：<code>ex:Obviously,this rabbit here runs very fast.</code></li><li>特殊：有些副词既可以当形容词也可以当副词，形容词变为副词是一般+ly(当然有不规则变化)</li></ol><h3 id="副词的作用">副词的作用</h3><ol><li>状语：<code>ex:This is a very fast rabbit.</code></li><li>表语：一般只在be后面. <code>ex:the wolf is abroad.</code></li><li>宾补：<code>let me out</code></li></ol><h3 id="副词的分类">副词的分类</h3><table><thead><tr><th>类型</th><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>方式副词</td><td>一般可以放在任意位置</td><td>Suddenly,the driver turned left.</td></tr><tr><td>程度副词</td><td>一般谓语修饰的形容词或者副词之前</td><td>He speaks very well</td></tr><tr><td>地点副词</td><td>一般在句尾,表强调的时候可以位于句首</td><td>The rabbit eats carrots indoors/outdoors.</td></tr><tr><td>时间副词</td><td>任意</td><td>The rabbit is eating some carrots now.</td></tr><tr><td>频率副词</td><td>大多位于行为动词之前，be动词/助动词/情态动词之后</td><td>The rabbit usually eats carrots.</td></tr><tr><td>疑问副词</td><td>差不多是疑问词</td><td>How does the rabbit eat carrots.</td></tr><tr><td>连接副词</td><td>起到连接句子的作用</td><td>I do not know where the rabbit eats carrots.</td></tr><tr><td>关系副词</td><td>和从句有关</td><td>That was the day when the rabbit ate the carrot for the first time.</td></tr><tr><td>句子副词</td><td>修饰整个句子</td><td>Obviously,this rabbit here runs very fast</td></tr></tbody></table><hr><h2 id="连词">连词</h2><h3 id="并列连词">并列连词</h3><p>并列连词：前后单词)或者短语或者句子)关系是平等的</p><p>如：<code>and</code> <code>ex:The rabbit not only teaches English but also makes videos</code> <code>ex:Neither the rabbit nor the wolf likes apples.</code> 遵循就近原则</p><ol><li>选择关系：<code>What does the rabbit like?Apples or carrots? | Hurry up,or/or else/otherwise you'll be late.</code></li><li>转折关系：虽然但是 but yet  <code>The rabbit cooked some carrots,yet he didn't eat any.</code></li><li>因果关系：<code>The rabbit is busy,so he won't go to the party tonight.</code>还有for、therefore等</li></ol><h3 id="从属连词">从属连词</h3><ol><li>引导名词性从句:<code>That the rabbit ate the carrot was obvious.</code></li><li>引导状语从句：when|while|as|before|after|until|since……具体示例看从句部分</li></ol><hr><h2 id="叹词与限定词">叹词与限定词</h2><p>负责表达情感的声音、单词、词组。</p><p>这一部分主要用于日常口语，对书面语影响不大。oh oh my God等就已经足够用了。</p><p>限定词：就是用于限定的词，这个属于词性定义，对语法影响不大。</p><p><strong>按位置划分</strong></p><ol><li>前位限定词：某些不定代词；倍数词；分数词…</li><li>中位限定词：冠词；物主代词；某些不定代词…</li><li>后位限定词：基数词；序数词；量词…</li></ol><p><code>ex:half(前位) my(中位) carrots.</code></p><hr><h1>构词法(重点)</h1><h2 id="派生">派生</h2><p>前缀+词根(核心、主要意思)+词缀(可改变词性)=单词(当然也可以三者排列组合)<br>注意：<strong>不是所有的词都和这三种成分有关，有些词根等表示的意思与通常的意思无关</strong>。用构词快速背记单词和认出单词，但还是要背，只是通过此规律能够减少压力。</p><ul><li>常见词根<ol><li>vis、aud、ed：分别代表视觉、听觉、吃，代表词有visible\audible\edible,这些词根实际上是“外来词汇”.</li><li>hydr：表示水   <code>ex:hydrated</code></li></ol></li><li>常见前缀<ol><li>In-：<ol><li>不 (否定义)<code>ex:invisible.</code> 是visible的反义，即不能看见的。</li><li>向里面：<code>ex:inward.</code> 向里面的。</li></ol></li><li>En-：使的   <code>ex:enlarge.</code> 使……变大。</li><li>Pre-：前面的</li><li>Suf-：后面的，在……之下。</li><li>Im-|Un-|il-|ir|mis-|dis-|de-|non-|:含否定意</li></ol></li><li>常见后缀<ol><li>ible：能被  <code>ex:credible.</code></li><li>able：能被 <code>ex:countable.</code></li></ol></li><li>字母变化： 变化是为了发音<ol><li>省略元音：struct+ure+al = structural</li><li>添加元音：pent+gon = pentagon</li><li>其他</li></ol></li></ul><h2 id="合成">合成</h2><p>比较常见于日耳曼词汇</p><p>如water→ waterfall waterproof underwater</p><p>还有一种是-合成。比如high-class</p><h2 id="混合">混合</h2><p>就是将词根、词缀分别只取一部分然后拼在一起。</p><p><code>ex:smoke+fog=smog</code></p><h2 id="截断">截断</h2><p>就是从单词上截取一部分当单词，一般和源单词意思相近。<code>ex：examination→exam</code> application→app</p><h2 id="缩写">缩写</h2><p>常用于专有名词(行业术语、网络流行词等)  ,一般将所有单词首字母大写然后拼起来。<code>ex:VIP(very important person)、BBC(British Broadcast Company)</code></p><h2 id="转换">转换</h2><p>即一个单词具有不同的词性，比如fall和education。</p><hr><h1>语法现象</h1><h2 id="被动">被动</h2><p>这里涉及到语态，即主动语态和被动语态，前者强调动作的执行者，后者强调动作的承受者。</p><p><strong>分类</strong></p><table><thead><tr><th>形式</th><th>解释</th><th>例子</th></tr></thead><tbody><tr><td>主+谓+宾</td><td>变被动为be+动词过去分词</td><td>The rabbit eat a carrot.=&gt;The carrot is eaten by the rabbit.  一般被动后面by+动作执行者，可加可不加。</td></tr><tr><td>主+谓+宾(直接宾语)+宾(简介宾语)</td><td>\</td><td>The carrot was given to the wolf by the rabbit.=The wolf was given the carrot by the rabbit.  原句为The rabbit gave the wolf the carrot.</td></tr><tr><td>主+谓+宾+宾补</td><td>对于如make这样的动词，主动改为被动时必须加to</td><td>The rabbit was invited to the party by the wolf./The rabbit made the wolf (to) laugh.=&gt;The wolf was made to laugh by the rabbit.</td></tr><tr><td>主+系+表</td><td>一般不能被动</td><td>I am smart</td></tr><tr><td>对于谓语是不及物动词</td><td>不存在动作的承受者，所以没有被动一说</td><td>the rabbit sleeps</td></tr></tbody></table><hr><h2 id="倒装">倒装</h2><p>倒装，即将谓语动词提前。主要分为完全倒装(谓语动词完全在主语前)和部分倒装(仅助动词提前)</p><p>也就是说，如果要写倒装句，<strong>最好是先写主动句然后再倒装</strong>。分类如下</p><h3 id="完全倒装：谓语动词完全在主语前">完全倒装：谓语动词完全在主语前</h3><ol><li>副词\介词短语在句首的倒装<ol><li>地点副词在句首：<code>ex:There goes the last bus=The last bus goes.</code> 这样强调谓语动词</li><li>时间副词在句首的倒装：<code>ex:Now comes the wolf's turn!</code> 以now和then用的居多。</li><li>表运动方向的副词在句首的倒装：<code>ex:Up went the carrots into the air.</code> 原句为<code>ex:The carrots went into the air.</code>.类似的词还有in\out\down\away……。</li><li>介词短语在句首的倒装：<code>ex:At the table sat a rabbit</code></li></ol></li><li>主语补语表语的倒装：将作表语的形容词、分词、介词短语、such置于句首时需要完全倒装。<code>ex:Seated on the ground is a group of rabbits.</code></li></ol><h3 id="部分倒装：仅助动词提前">部分倒装：仅助动词提前</h3><ol><li>句首有否定意义词时的倒装 ：<code>ex:Never before have I eaten such a delicious carrot.</code></li><li>句首有&quot;only&quot;时的倒装 ：<code>ex:Only in this way can we grow delicious carrots.注；only句首如果修饰主语不用倒装。</code></li><li>&quot;if…should.构成虚拟语气的倒装 ：<code>ex:Should I win the lottery, I would buy a huge pile of carrots。</code>= <code>ex:If I should win the lottery,I would buy a huge pile of carrots.</code></li><li>固定句型中的倒装：<code>ex:Rabbits love eating carrots;so do wolves.</code></li></ol><h3 id="形式倒装：谓语动词不提前，仅将强调内容放置句首。">形式倒装：谓语动词不提前，仅将强调内容放置句首。</h3><ol><li>感叹句中的倒装 ：<code>ex:What a delicious carrot it is!</code></li><li>比较级句型中的倒装(如&quot;the more.,the more.&quot;) ：<code>ex:The more carrots you eat,the healthier you become.</code></li><li>“however’”;&quot;whatever’&quot;引导让步状语从句时的倒装 ：<code>ex:However long this video is,you should watch it till the end.</code></li><li>“as”,&quot;though&quot;引导让步状语从句时的倒装：<code>ex:Much as he likes the carrot,he doesn't want to eat it.</code></li></ol><hr><h2 id="强调">强调</h2><p>口语强调：重读即可; 语气词强调：见前面的叹词部分。书面强调：黑体字，大小写。</p><p><strong>常见的强调</strong></p><table><thead><tr><th>形式</th><th>例子</th></tr></thead><tbody><tr><td>really、very、just、ever……用附加词突出强调</td><td>Rabbits really like carrots.</td></tr><tr><td>重复说某一个词</td><td>listen to me,listen to me,very very carefully.</td></tr><tr><td>助动词</td><td>Rabbits do like carrots!</td></tr><tr><td>强调代词</td><td>I can do it myself!这里的myself是强调作用，去掉它原句意思不变</td></tr><tr><td>倒装</td><td>Not a single carrot did I eat yesterday</td></tr><tr><td>感叹句</td><td>How big the carrot is!</td></tr><tr><td>固定句式</td><td>it +be+that……句式:It is the rabbit who/that will eat the carrot.要强调的东西放在it is和that 之间 判断强调句也是看去掉it’s who\that 是否构成完整的句子。</td></tr></tbody></table><hr><h2 id="省略">省略</h2><h3 id="省略冠词">省略冠词</h3><ol><li>独一无二的名词前面，如<code>ex:chairman/president/head</code> <code>ex:The rabbit was appointed (the) chairman of the Carrotown Committee.</code></li><li>并列关系：<code>ex:Both the rabbit and (the) wolf will be invited to the party.</code>表示并列的词，第二个冠词可以去掉。注意如果去掉冠词之后意思改变就不能去掉冠词如：<code>ex:a teacher and video creator!=a teacher and a video creator</code></li><li>某些独立主格结构:<code>ex:The rabbit came in,carrot in hand.</code>省略了with</li></ol><h3 id="省略介词">省略介词</h3><ol><li>时间介词：<code>ex:I worked 60 hours last week.</code>在60前面省略了for</li><li>作某事：<code>ex:I am busy (in) making videos.</code></li></ol><h3 id="省略动词不定式">省略动词不定式</h3><ol><li>并列关系：<code>ex:He wanted to stay here and(to) read.</code></li><li>不定式中的裸不定式：<code>ex:The wolf made me (to) watch the video.</code></li><li>省略从句引导词：<code>ex:This is the rabbit (that) we met yesterday.</code>仅限于限定性定语从句</li></ol><h3 id="句法省略">句法省略</h3><ol><li>祈使句：<code>ex:open the door ,please.</code>省略了主语you</li><li>感叹句省略：<code>ex:What a smart rabbit!</code>省略了he is</li><li>口语：<code>ex:what did you eat? (I ate)a carrot,</code>还有很多，看实际</li><li>并列句:<code>ex:The rabbit went home after work,and (the rabbit) ate a carrot.</code></li><li>复杂句：<code>ex:The rabbit will eat the carrot,but I don't know when (he will eat it).\(I am) sorry to hear that</code> 还有than\if possible等这样的词所在句子也有省略。</li></ol><hr><h2 id="主谓一致">主谓一致</h2><p>看这个句子<code>you were late.</code> 主语you和were共同传递了“第二人称，一般/过去“这个信息，即主语和谓语动词传递的信息是一致的。主谓一致分为三类</p><h3 id="语法一致">语法一致</h3><ol><li>谓语动词单复数和主语单复数一致：如<code>ex:time is money。</code>注意不定式主语和动名词主语谓语动词用单数。<code>ex:To eat a carrit every day is good for the rabbit.</code></li><li>特殊-假象主语：如<code>ex:as well as\except\but</code> <code>ex:The rabbit as well as other animals gets a carrot.</code>一般遵循就远原则。其本质就是这里的短语看起来像有两个主语实际上只有一个。</li><li>不定代词作主语：如everyone\each of 接单数:<code>ex:Each of them gets a carrot.</code>，both of\some of接复数:<code>ex:Both of them like carrots.</code>   none of\neither of 接单复数都行  <code>ex:None of them get/gets a carrot.</code></li></ol><h3 id="意义一致">意义一致</h3><ol><li>同一个主语多重身份：<code>ex:The teacher and video creator is a rabbit.</code>这位老师兼视频创作者是只兔子。这个例子也提醒我们<strong>不要看到and就用复数</strong></li><li>复数名词的单数意义：<code>ex:Ten years is a long time.</code>十年是一个时间段，<strong>看它是否表达的是整体而非个体的概念</strong>。<code>ex:A knife and fork is needed for eating the carrot.</code> 这里的意思可不是一把刀和一副叉子，而是整体意义“一副刀叉”.</li><li>不定代词的单复数意义：all are quiet)大家都很安静) all is quiet(一切都很安静)也就是看不定代词到底表示什么意思。</li><li>名词的形和意：主要看意思，意思是复数谓语动词就用复数。</li><li>特殊：单复数同形名词<code>ex:A sheep is eating grass.\\The sheep are eating grass.</code> 第一个句子指的是一只绵羊，第二个句子指的是一群绵羊。集合名词：理论上用单复数都行。如：deer fish team……也是主要看意思，意思是复数谓语动词就用复数。</li></ol><h3 id="就近一致">就近一致</h3><p>谓语动词的单复数由最近的主语决定。</p><ol><li>Or|either or……|not only……but also|not but|neither nor：<code>ex:Not only the rabbit but also many other animals like carrots.</code></li><li>There be：<code>ex:There is a carrot and two apples on the table.</code></li></ol><hr><h2 id="英语标点">英语标点</h2><p>本段主要侧重于书面语的书写规范。分类如下</p><h3 id="逗号：断句">逗号：断句</h3><ol><li>断句：<code>ex:Let's eat,the wolf.</code></li><li>列举：<code>ex:Let's eat carrots,apples and bananas.</code> 提醒，如果有定语修饰，但是只修饰一个的话也需要用逗号隔开。<code>ex:Let's eat carrots,red apples ,and bananas.</code>这里强调的是红色的苹果和普通的香蕉，如果不在and前面加逗号就变成了红色的苹果和香蕉。</li><li>同位语：<code>ex:I love my parents,the rabbit and the wolf.</code>我爱父母，(它们分别是)兔子和狼。如果不想表达同位语，同样在and前面加上逗号。</li><li>引语：<code>ex:The wolf said to the rabbit,&quot;Let'seat,rabbit.&quot;&quot;Well,yes,let's eat,my dear wolf,&quot;said the rabbit.</code> 第一句逗号之后的引语开头大写，而如果引语在前，则末尾要使用逗号。</li><li>插入语：<code>ex:&quot;Well,yes,&quot;said the rabbit,&quot;let's eat,my dear wolf.&quot;</code>中间的一句就是插入语</li><li>并列句、复杂句：<code>ex:The rabbit ate some carrots,but he was still hungry</code></li><li>附加疑问句：<code>ex:This is a tasty carrot,isn't it?</code> 个人感觉更像反问语句。</li><li>时间地点数字格式：<code>Dec 1st,2021|Chengdu,Sichuan,China.</code>记住英语中时间和地点的表示方法。</li></ol><h3 id="句号">句号</h3><p>注意：英文的句号是一个实心的点”.”，不要写成中文的“。”。</p><p>句子说完就加句号</p><h3 id="分号：并列，有关">分号：并列，有关</h3><p><code>ex:The rabbit likes carrots;the wolf likes apples.</code></p><h3 id="冒号：">冒号：</h3><ol><li>列举： <code>ex:We have two lunch options:carrots,apples</code></li><li>引语：<code>ex:The rabbit: I want to eat carrots.</code> 原句是  <code>The rabbit said,&quot;I want to eat carrots.&quot;</code></li><li>主标题，副标题： <code>ex:Carrots:Rabbits'Favorite Food</code>  <code>ex:Sakiro:Shadows Die Twice.</code></li><li>时间表达：<code>ex:at 8:00</code></li></ol><h3 id="引号：和中文用法基本一致">引号：和中文用法基本一致</h3><p><code>Please don't be a &quot;freeloader&quot;</code> 可以表强调。</p><p>注意英文中没有书名号，一般都是用引号表示的<code>ex:Have you read &quot;The Little Prince&quot;</code> 或者用斜体。<em>The Little Prince</em></p><h3 id="破折号">破折号</h3><p>和中文用法一样，比中文短：<code>ex:You've met my best friend-the wolf.</code>或者表示句子中断</p><h3 id="问号和感叹号">问号和感叹号</h3><p>不多解释，问号用于问句，感叹号用于感叹句</p><h3 id="连字符，撇号">连字符，撇号</h3><p>前者是构词，后者用于所有格或者省略 <code>ex:Hard-working</code> <code>ex:The rabbit's carrots\you'd better finish it first.</code></p><h3 id="省略号">省略号</h3><p>英文的省略号只有三个点，而且居下 <code>ex:To be continued...</code></p><h1>参考</h1><ol><li><a href="https://www.bilibili.com/video/BV1XY411J7aG?p=29&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">英语语法精讲合集 (全面, 通俗, 有趣 | 从零打造系统语法体系)</a></li><li><a href="https://excalidraw.com/#:~:text=Excalidraw%20is%20a%20virtual%20collaborative%20whiteboard%20tool%20that">Excalidraw绘图网站</a></li><li><a href="https://www.yingyutu.com/">英语兔 (yingyutu.com)</a> 其实是微信公众号不是网站</li><li><a href="https://dictionary.cambridge.org/zhs/%E8%AF%8D%E5%85%B8/">免费的剑桥英语词典和同义词词典 (cambridge.org)</a></li></ol>]]></content>
    
    
    <summary type="html">教你基础的英语语法，为后续的专业英语和写作等打下坚实的基础。</summary>
    
    
    
    <category term="English" scheme="https://lloydkai.cn/categories/English/"/>
    
    
    <category term="English" scheme="https://lloydkai.cn/tags/English/"/>
    
  </entry>
  
  <entry>
    <title>数据分析工具superset安装和使用(version:0.381)</title>
    <link href="https://lloydkai.cn/posts/superset/"/>
    <id>https://lloydkai.cn/posts/superset/</id>
    <published>2024-09-16T04:50:21.000Z</published>
    <updated>2026-04-23T01:44:16.672Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/06/10/R21dguZMKpAPhNf.png" alt></p><h1>简介</h1><p>superset是一个开源的现代数据探索和可视化平台。目前属于Apache孵化器项目，主要用于数据分析师进行数据可视化工作,</p><h1>准备工作</h1><blockquote><p>注意：superset官网<a href="https://superset.apache.ac.cn/docs/intro/">简介 | Superset 中文 (apache.ac.cn)</a> 推荐使用docker安装，而以下教程是手动配置环境，建议不熟悉开发环境的用docker安装(我再也不手动配置了o(╥﹏╥)o)</p></blockquote><ul><li>事先安装centos7(或者有一个服务器)并且安装好mysql</li><li>主要参考视频教程和资料<ul><li><a href="https://www.bilibili.com/video/BV1SL4y1a7WK?p=10&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">尚硅谷大数据Superset教程（数据仓库项目首选数据可视化平台）</a></li><li><a href="https://blog.csdn.net/m0_46914845/article/details/125868049#comments_26566111">数据仓库工具superset安装（完全可用）-CSDN博客</a></li></ul></li></ul><h1>基本环境配置</h1><ol><li>尚硅谷的视频先从P1看到P2，一步步按照视频讲的方法做即可</li><li>然后就要开始创建Python环境，注意这里根据我个人实操和网络上帖子的经验，3.7、3.8的环境都有问题，我尝试过3.9，但是在最后启动superset的时候总是无法访问。这里就不要完全照抄视频，而是要根据此博客<a href="https://blog.csdn.net/m0_46914845/article/details/125868049#comments_26566111">数据仓库工具superset安装（完全可用）-CSDN博客</a> ，建议安装3.6版本的Python，按照步骤做到第六步。</li><li>然后注意将命令中所有的<code>https://pypi.douban.com/simple/</code> 改成 <code>https://pypi.tuna.tsinghua.edu.cn/simple</code></li><li>执行后发现没有安装pip和wheel，查看此<a href="https://blog.csdn.net/qq_15098623/article/details/90905230">centos 如何安装 pip（解决No package python-pip available问题）_no package python37 available-CSDN博客</a> 安装好</li><li>在执行第九步的时候输入命令可以加上 <code>-i https://pypi.tuna.tsinghua.edu.cn/simple</code>加快下载速度</li><li>在执行第十步的时候发现缺少模块 输入 <code>pip install --upgrade cryptography==3.2 -i https://pypi.tuna.tsinghua.edu.cn/simple</code>  安装</li><li>后面基本上就是照着做了，注意–bind：绑定本机地址 ，绑定的是你服务器的IP地址</li><li>环境安装好之后就可以看尚硅谷的视频继续学了。</li></ol><h1>superset使用指南</h1><p>待更新……</p>]]></content>
    
    
    <summary type="html">教你如何安装superset,为后续使用superset做准备</summary>
    
    
    
    <category term="大数据" scheme="https://lloydkai.cn/categories/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
    
    
    <category term="Linux" scheme="https://lloydkai.cn/tags/Linux/"/>
    
    <category term="大数据" scheme="https://lloydkai.cn/tags/%E5%A4%A7%E6%95%B0%E6%8D%AE/"/>
    
  </entry>
  
  <entry>
    <title>hexo博客系列(二)博客创建指南</title>
    <link href="https://lloydkai.cn/posts/blog-series-two/"/>
    <id>https://lloydkai.cn/posts/blog-series-two/</id>
    <published>2024-06-12T13:44:34.000Z</published>
    <updated>2026-04-23T01:46:47.631Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/13/tfez8CIgnwY5iJh.jpg" alt></p><h1>简介</h1><p>Hexo 是一个由Nodejs驱动的博客框架，支持 Markdown、一键部署、插件和多种模板引擎。Hexo 可以让你轻松创建、管理和部署你的个人或团队博客。本文基于个人的实践经验，<strong>以Windows为主要开发环境</strong>，旨在让那些对博客搭建感兴趣但碍于困难的朋友能搭建起基本的博客框架。</p><h1>准备工作</h1><h2 id="课前提醒——主要是针对非程序员">课前提醒——主要是针对非程序员</h2><p><strong>大部分的操作、代码输入</strong>都是在<strong>Windows</strong>系统<strong>终端</strong>中执行的。</p><p><strong>方法</strong>：点击开始-搜索“终端”-打开，或者在任意文件夹中“右键”-“在终端中打开”。会出现黑色的框。后续大部分代码都是在这“黑框”中输入且执行的。</p><p><img src="https://s2.loli.net/2024/11/26/2q15iMDwhdxRHPb.png" alt="博客创建指南01"></p><ul><li>代码块没有标明代码语言的都是在Windows终端中运行的。mac系统和linux系统相关指令请查询有关资料</li><li>默认电脑下载了git和注册了github。没有注册github和下载git的可以看这个<a href="https://www.bilibili.com/video/BV1o5411j7up/?buvid=XY8FE9283F9E25662FCF4765F2CEBCB3B2141&amp;from_spmid=main.space-search.0.0&amp;is_story_h5=false&amp;mid=ueF2Y5ca46qLJ%2B0TtsIVXA%3D%3D&amp;p=2&amp;plat_id=116&amp;share_from=ugc&amp;share_medium=android&amp;share_plat=android&amp;share_session_id=26f5f2ef-15df-4762-87af-a60e30f96419&amp;share_source=COPY&amp;share_tag=s_i&amp;spmid=united.player-video-detail.0.0&amp;timestamp=1718194497&amp;unique_k=7ayW8ON&amp;up_id=456828781&amp;vd_source=9d7958a1b86a1d76c255b26c5fa353b7">github入门及如何提交代码-清晰版本_哔哩哔哩_bilibili</a></li><li>默认会“科学上网”，不会的可以参考此大佬的教程<a href="https://mubu.com/doc/5OeZGO2XKgh">搭建个人博客网站 - 幕布 (mubu.com)</a>，可以在他的博客中搜索&quot;搭建个人博客“   <a href="https://starlike-daydream.github.io/Cesteo.github.io/">Ceasteo’s Blog</a>。按照此大佬的方法也可以实现简单的hexo博客创建。<strong>注意大佬文档中的淘宝镜像已经失效,请换成</strong><code>https://registry.npmmirror.com</code></li></ul><h2 id="相关资料下载">相关资料下载</h2><ol><li><a href="https://nodejs.cn/">Node.js 中文网 (nodejs.cn)</a>安装，进去后点击下载安装，选择长期支持版（LTS）即可</li></ol><p><img src="https://s2.loli.net/2024/11/26/BZNOMvsk15YIKr8.png" alt="博客创建指南02"></p><ol start="2"><li>安装cnpm并配置淘宝镜像</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g cnpm --registry=https://registry.npmmirror.com</span><br></pre></td></tr></table></figure><p><img src="https://s2.loli.net/2024/11/26/J9FsPLaTqZ1Ygb8.png" alt="博客创建指南03"></p><blockquote><p><strong>注意</strong>：后面代码中我打//并且后面跟着文字的（比如//这里是初始化)都是<strong>注释</strong>，<strong>不要写在终端里面</strong></p></blockquote><ol start="3"><li>测试cnpm是否安装</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cnpm -v   </span><br></pre></td></tr></table></figure><p><strong>v</strong>：version 版本的意思</p><ol start="4"><li>安装hexo博客框架</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cnpm install -g hexo-cli</span><br></pre></td></tr></table></figure><ol start="5"><li>测试hexo博客框架是否安装</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo -v</span><br></pre></td></tr></table></figure><h2 id="初始化博客">初始化博客</h2><blockquote><p>后续可以通过blog文件(<strong>shift+鼠标右键-在终端中打开</strong>）直接进入终端，也可以用Visual Studio Code将此文件打开并创建终端（建议使用vscode，后续博客维护很方便）。</p></blockquote><ol start="6"><li>在空文件夹（我这里事先创建并将其命名为temp)中初始化hexo博客框架,然后通过cd指令进入此目录。</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">//示例：cd .\Desktop\temp\</span><br><span class="line">hexo init</span><br><span class="line">//如果报错的话就输入cnpm install 然后再输入hexo s即可</span><br></pre></td></tr></table></figure><ol start="7"><li>启动博客  start   用来预览修改后的博客 按ctrl+c即可停止运行。</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo s</span><br></pre></td></tr></table></figure><ol start="8"><li>清除博客内容</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo clean  //或者hexo cl</span><br></pre></td></tr></table></figure><ol start="9"><li>生成博客内容</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo g</span><br></pre></td></tr></table></figure><h2 id="部署">部署</h2><p><strong>我这里只讲解部署到github的思路</strong>，部署到其他平台或者服务器请自行查询有关资料。没有注册github和git的可以看这个<a href="https://www.bilibili.com/video/BV1o5411j7up/?buvid=XY8FE9283F9E25662FCF4765F2CEBCB3B2141&amp;from_spmid=main.space-search.0.0&amp;is_story_h5=false&amp;mid=ueF2Y5ca46qLJ%2B0TtsIVXA%3D%3D&amp;p=2&amp;plat_id=116&amp;share_from=ugc&amp;share_medium=android&amp;share_plat=android&amp;share_session_id=26f5f2ef-15df-4762-87af-a60e30f96419&amp;share_source=COPY&amp;share_tag=s_i&amp;spmid=united.player-video-detail.0.0&amp;timestamp=1718194497&amp;unique_k=7ayW8ON&amp;up_id=456828781&amp;vd_source=9d7958a1b86a1d76c255b26c5fa353b7">github入门及如何提交代码-清晰版本_哔哩哔哩_bilibili</a></p><ol start="10"><li>github创建仓库,注意格式严格为<code>你的github用户名.github.io</code> 并复制SSH的clone地址，我这里以Tom为例</li></ol><p><img src="https://s2.loli.net/2024/11/26/Ju7GXhRZjFKTbSQ.png" alt="博客创建指南04"></p><ol start="11"><li>安装部署插件</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cnpm install --save hexo-deployer-git</span><br></pre></td></tr></table></figure><ol start="12"><li>修改_config.yml文件</li></ol><p><img src="https://s2.loli.net/2024/11/26/ij6X1BzdSGuLOnm.png" alt="博客创建指南05"></p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">//一般是最后一行。</span></span><br><span class="line"><span class="attr">deploy:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">&#x27;git&#x27;</span></span><br><span class="line">  <span class="attr">repository:</span> <span class="string">粘贴你10步复制的地址。</span></span><br><span class="line">  <span class="attr">branch:</span> <span class="string">master</span></span><br></pre></td></tr></table></figure><ol start="13"><li>部署到github</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure><ol start="14"><li><p>13步后有的会提示输入github账号密码，没有就跳过14和15步</p></li><li><p>分别输入用户名与密码。</p></li></ol><p>输入密码之后报错并<strong>提醒你github已经停止使用密码登录</strong>，需要用密钥或者是ssh，这里我采用ssh的方式。</p><ol start="16"><li>初始化用户名与邮箱(“yourname”和”youremail“改成你之前注册github设置的)</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name &quot;yourname&quot; //（注意user.name/email和英文双引号&quot;之间要有一个空格）</span><br><span class="line">git config --global user.email &quot;youremail&quot;</span><br></pre></td></tr></table></figure><ol start="17"><li>确认是否设置成功</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">//用户名与邮箱</span><br><span class="line">git config --global user.name</span><br><span class="line">git config --global user.email</span><br></pre></td></tr></table></figure><ol start="18"><li>下载github部署插件</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure><ol start="19"><li>本地生成密钥</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -C &quot;youremail&quot;（这里改为16步你设置的邮箱）</span><br></pre></td></tr></table></figure><ol start="20"><li>获取你生成的密钥，并复制返回的结果</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat ~/.ssh/id_rsa.pub</span><br></pre></td></tr></table></figure><ol start="21"><li><p><strong>登录github</strong>, 点击头像——settings——点击SSH and GPG keys-再点击New SSH key,自己取一个标题,然后将复制的密钥粘贴到&quot;key&quot;文本框内并提交（Add SSH key)。</p></li><li><p>验证：</p></li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh -T git@github.com</span><br></pre></td></tr></table></figure><ol start="23"><li>再次提交</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure><ol start="24"><li>运行并检验是否成功</li></ol><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo s   //或者在浏览器URL栏输入“你的github用户名.github.io”，验证是否已经部署。</span><br></pre></td></tr></table></figure><p>至此你已经成功部署一个简单的hexo博客，恭喜你我的朋友(<sup>o</sup>)/~，<strong>但这只是伟大征程的第一步，这是结束也是开始</strong>……</p><h1>博客维护</h1><h2 id="基础指令">基础指令</h2><p>主题、文章修改之后要重新生成并部署。<br>简单讲解：</p><ol><li><code>hexo cl</code> 清除之前生成的静态文件(html,css,js)</li><li><code>hexo g</code> 生成静态文件到public文件夹下</li><li><code>hexo s</code> 在本地主机localhot:4000下运行</li><li><code>hexo d</code> 将静态文件提交到github上(插件)</li></ol><blockquote><p>总结：<strong>最重要的是第2,4个代码（部分插件使用需要第一个代码，这样通过你的用户名.github.io打开的博客才会更改。</strong></p></blockquote><h2 id="md文件">md文件</h2><p><strong>命令行创建md文件</strong><br><code>hexo n &quot;博客文章名&quot;</code>， <strong>必须先进入到文件中才能使用</strong>，会自动在 你所创建的文件夹\source_posts\博客文件名.md  路径下创建一个md文件。</p><p><strong>md文件保存位置</strong><br>一般就在/_ posts 文件下创建md文件即可（或者把md文件移动到这里），要在开头加上如下语句即可.<strong>注意冒号后面要留空格</strong></p><p><strong>示例格式如下</strong></p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">&lt;! -- 这里是html的注释 写的时候不要添加 - - &gt;</span><br><span class="line">title: 我的第一篇博客文章</span><br><span class="line">date: 2024-06-01  19:10:34</span><br><span class="line">tags: C++</span><br><span class="line">no<span class="emphasis">_valine: true&lt;!- - 关闭评论- - &gt;</span></span><br><span class="line"><span class="emphasis">comments: 是否开启评论(true or false)</span></span><br><span class="line"><span class="emphasis">top: &lt;!- - 文章置顶true- - &gt;</span></span><br><span class="line"><span class="emphasis">no_</span>word<span class="emphasis">_count: true&lt;!- -关闭字数统计- - &gt;</span></span><br><span class="line"><span class="emphasis">password: &lt;! - -如果加密，这里填写密码 - - &gt;</span></span><br><span class="line"><span class="emphasis">reward: true&lt;!- - 当前文章是否开启打赏 - - &gt;</span></span><br><span class="line"><span class="emphasis">copyright: true&lt;!- - 当前文章是否开启版权声明 - - &gt;</span></span><br><span class="line"><span class="emphasis">categories: &lt;! - -如下，分类2是分类1的子分类- - &gt;</span></span><br><span class="line"><span class="emphasis">- [分类1，子分类1]</span></span><br><span class="line"><span class="emphasis">- [分类1，子分类2]</span></span><br><span class="line"><span class="emphasis">- [分类2]</span></span><br><span class="line"><span class="emphasis">tags: </span></span><br><span class="line"><span class="emphasis">- 标签1</span></span><br><span class="line"><span class="emphasis">- 标签2</span></span><br></pre></td></tr></table></figure><h2 id="插件下载与使用">插件下载与使用</h2><p><strong>提醒：少即是多, 避免华而不实。</strong></p><p>打开官方文档<a href="https://hexo.io/zh-cn/docs/">文档 | Hexo</a>，点击插件，点击中意的插件，按照作者的教程去配置插件</p><p><strong>举例</strong><br><strong>DPlayer插件</strong></p><p><strong>播放代码</strong><br><code>&#123;% dplayer "url=" "pic=" "theme=#FADFA3" "autoplay=false" "mutex=true" %&#125;</code></p><p><strong>示例</strong><br>打开对应视频资源网页版（这里以b站为例），鼠标移动到分享-“嵌入代码”，将代码复制到md文件里面，如果需要调整大小，可添加<code>height=450 width=600</code> ,根据需要调整即可</p><h2 id="主题的下载与使用">主题的下载与使用</h2><p><strong>安装思路同插件</strong><br>注意在themes界面中可以点击“visit preview site”预览主题。</p><ol><li>看作者介绍如何安装，一步步安装  ，复杂一点的主题还有一系列插件安装</li><li>打开根目录下的_config.yml  将theme: 以前的主题 改为 theme: 现在的主题</li><li>后续的改动都是要基于作者文档。熟悉前端开发的朋友可以用“<strong>检查</strong>“了解作者网页的结构，然后自行修改</li></ol><p><strong>推荐主题</strong>：</p><ul><li>极简风格：<ul><li>yilia-plus：<a href="https://github.com/JoeyBling/hexo-theme-yilia-plus">一个简洁优雅的hexo主题</a></li></ul></li><li>优雅又实用：<ul><li>butterfly：<a href="https://butterfly.js.org/posts/21cfbf15/">Butterfly 安裝文檔(一) 快速開始 | Butterfly</a></li><li>matery：<a href="https://github.com/blinkfox/hexo-theme-matery/blob/develop/README_CN.md">hexo-theme-matery/README_CN.md</a></li></ul></li></ul><h1>Hexo进阶-butterfly主题安装及其定制化</h1><blockquote><p>我目前安装的是5.1.0版本的。</p></blockquote><p>虽然主菜单栏里面可以分成多个子菜单，但是似乎每一个子菜单只能放一个md文件，所以<u>建议此md文件作为某一类型的东西的索引来呈现。</u></p><p>所有的博客md文件都需要放在_post文件夹里面，其他地方大多只能放索引md文件。<strong>建议使用</strong><code>hexo n post 标题名</code> ,这样就会<strong>自动将对应的文件夹也生成</strong>。</p><p>建议修改的使用经常使用Hexo s命令，修改无误之后再提交。</p><p><strong>To be continue……</strong></p><hr><h1>总结</h1><p>本篇文章主要侧重于基础的hexo博客搭建，至于进阶的hexo主题搭建和插件安装，限于笔者能力难以展开，有兴趣的读者可以去官方文档找对应的资料，按照作者的文档去安装。</p><h1>结束语</h1><p>有的朋友会说这也太难了吧，确实对于零基础的小白配置一个复杂的博客主题绝非易事，但是我想用王安石的一句话共勉想要变得更强、超越自我的朋友。<br><strong>“而世之奇伟、瑰怪、非常之观，常在于险远，而人之所罕之焉，故非有志者不能之也。”</strong></p><h1>参考资料</h1><ol><li><strong>官方网站</strong>：<a href="https://hexo.io/zh-cn/docs/">文档 | Hexo</a></li><li><strong>其他人的教程</strong>：<a href="https://mubu.com/doc/5OeZGO2XKgh">搭建个人博客网站 - 幕布 (mubu.com)</a></li><li>git和github<strong>下载和使用</strong>：<a href="https://www.bilibili.com/video/BV1o5411j7up/?buvid=XY8FE9283F9E25662FCF4765F2CEBCB3B2141&amp;from_spmid=main.space-search.0.0&amp;is_story_h5=false&amp;mid=ueF2Y5ca46qLJ%2B0TtsIVXA%3D%3D&amp;p=2&amp;plat_id=116&amp;share_from=ugc&amp;share_medium=android&amp;share_plat=android&amp;share_session_id=26f5f2ef-15df-4762-87af-a60e30f96419&amp;share_source=COPY&amp;share_tag=s_i&amp;spmid=united.player-video-detail.0.0&amp;timestamp=1718194497&amp;unique_k=7ayW8ON&amp;up_id=456828781&amp;vd_source=9d7958a1b86a1d76c255b26c5fa353b7">github入门及如何提交代码-清晰版本_哔哩哔哩_bilibili</a></li></ol>]]></content>
    
    
    <summary type="html">教你如何创建一个简单的hexo博客</summary>
    
    
    
    <category term="blog" scheme="https://lloydkai.cn/categories/blog/"/>
    
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="blog" scheme="https://lloydkai.cn/tags/blog/"/>
    
    <category term="hexo" scheme="https://lloydkai.cn/tags/hexo/"/>
    
  </entry>
  
  <entry>
    <title>hexo博客系列(一)更新公告</title>
    <link href="https://lloydkai.cn/posts/blog-series-one/"/>
    <id>https://lloydkai.cn/posts/blog-series-one/</id>
    <published>2024-06-10T01:22:57.000Z</published>
    <updated>2026-04-23T02:39:54.495Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://s2.loli.net/2024/10/22/8KJE1CP3nTIDFWm.jpg" alt></p><h1>hexo博客更新公告</h1><div class="timeline green"><div class="timeline-item headline">        <div class="timeline-item-title">          <div class="item-circle"><p>2026</p></div>        </div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>4-23</p></div>        </div>        <div class="timeline-item-content"><ol><li>首页添加了RSS订阅功能</li><li>更改了网站图标</li><li>所有文章添加了文前封面，便于RSS展示和阅读</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>4-18</p></div>        </div>        <div class="timeline-item-content"><ol><li>留言系统已经从vercel迁移到netlify上，国内访问速度明显加快</li><li>开启反垃圾系统，提升安全性</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>4-9</p></div>        </div>        <div class="timeline-item-content"><!-- timeline 4-15 --><ol><li>ICP、公安等已成功备案，并且添加在网站首页页脚处。</li><li>优化了留言功能，现在可以正常接收到评论信息和机器人信息。</li><li>使用了51LA的统计API，移除了不算子的统计脚本</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>4-9</p></div>        </div>        <div class="timeline-item-content"><ol><li>将博客部署到阿里云的服务器上，并配置相应的域名，正在等待备案中</li><li>优化了页脚和友链，符合备案规定</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>3-19</p></div>        </div>        <div class="timeline-item-content"><ol><li>优化了上方菜单栏的布局和展示</li><li>更新了站主公告，龙王考研回归(笑)</li></ol></div>      </div></div><div class="timeline green"><div class="timeline-item headline">        <div class="timeline-item-title">          <div class="item-circle"><p>2025</p></div>        </div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>6-1</p></div>        </div>        <div class="timeline-item-content"><ol><li>魔改了页脚</li><li>改变首页背景图像并添加雪花效果</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>5-31</p></div>        </div>        <div class="timeline-item-content"><ol><li>首页添加了轮播图，移除了磁贴</li><li>优化了侧边栏部分，修改了首页布局风格</li><li>魔改并自定义了预加载动画</li><li>优化了文章链接，不用冗余的数字作为链接</li><li>移除了隐私用户政策</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>3-1</p></div>        </div>        <div class="timeline-item-content"><ol><li>本blog从zeabur迁移到vercel并更换了一个域名，后续会找一个稳定的服务器。</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>2-14</p></div>        </div>        <div class="timeline-item-content"><ol><li>butterfly主题从5.1.0更新到5.3.2版本(以后一年更新一次版本)</li><li>美化了界面(魔改教程)</li><li>将原来的文字显示部分作了宽屏适配</li></ol></div>      </div></div><div class="timeline green"><div class="timeline-item headline">        <div class="timeline-item-title">          <div class="item-circle"><p>2024</p></div>        </div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>11-9</p></div>        </div>        <div class="timeline-item-content"><ol><li>在网页/privacy下添加了隐私用户政策</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>10-29</p></div>        </div>        <div class="timeline-item-content"><ol><li>修复了手机端视频溢出显示部分的问题</li><li>修改了几处笔误和显示问题。</li><li>优化了所有博客的参考部分</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>10-26</p></div>        </div>        <div class="timeline-item-content"><ol><li>butterfly主题从5.0.0更新到5.1.0版本</li><li>优化了chart插件</li><li>更新了一篇新博客</li></ol></div>      </div><div class="timeline-item">        <div class="timeline-item-title">          <div class="item-circle"><p>10-10</p></div>        </div>        <div class="timeline-item-content"><ol><li>butterfly主题从4.13.0更新到5.0.0版本</li><li>首页添加了磁贴,修复了磁贴名字和描述不匹配的问题</li><li>更新了留言板</li><li>优化了搜索功能</li><li>禁止B站视频自动播放</li><li>更新了主页“关于”部分</li><li>修复了几处笔误的问题</li><li>优化了评论功能的选择</li><li>添加了站点工具(谷歌与必应)，优化了文章的描述部分</li><li>优化一下图片无法放大查看的问题</li></ol></div>      </div></div><h2 id="未来更新内容">未来更新内容</h2><h3 id="已更新内容">已更新内容</h3><ul><li>[x] 目前已主要确定S.EE作为图床，以后根据需要换成aliyun的OSS作为图床，<strong>需要配置其URL为自定义域名之后才能用</strong>，参考链接：<a href="https://blog.csdn.net/fsjwin/article/details/114644687">https://blog.csdn.net/fsjwin/article/details/114644687</a> 要花费一定的时间，如果成功就续费。</li><li>[x] <strong>添加一些CDN加快图片加载速度和其他相关资源速度</strong>。<a href="https://blog.cpen.top/posts/9b5a2768.html">06_Hexo-elemecdn 加速 Butterfly 第三方资源 | Mycpen</a> 、<a href="https://blog.zhheo.com/p/790087d9.html#%E6%96%B0%E7%89%88butterfly">Butterfly CDN链接更改指南，替换jsdelivr提升访问速度 | 张洪Heo</a>  截止目前<strong>有相当一部分已经404了</strong></li><li>[x] busuanzi的统计优化——已换成51La的统计</li><li>[x] 换一个好一点的域名，比如com或者cn——已换成lloydkai.cn的域名</li><li>[x] 部署到国内的服务器(优先阿里云)并备案。参考网站域名申请<a href="https://tech.yemengstar.com/hexo-tutorial-use-your-domain-beginner/">为HEXO绑定自己的域名</a></li><li>[x] <a href="https://luckysusu.top/post/hexo_emoji.html">让hexo博客支持emoji表情</a></li><li>[x] 评论系统的优化</li></ul><h3 id="待更新内容">待更新内容</h3><ul><li>[ ] <a href="https://www.linuxwf.com/2020/04/09/Hexo-Aplayer%E6%92%AD%E6%94%BE%E5%99%A8/#%E6%AD%8C%E8%AF%8D%E6%A0%87%E7%AD%BE">自定义aplayer</a>  由于大部分歌曲都需要VIP，后面就使用自己的资源文件夹。</li><li>[ ] 子菜单展示内容；方法：通过基本的markdown语言和butterfly专有语法-标签外挂实现效果，建议写成总领式的文章或者展示页面。可以参考此博客<a href="https://blog.guole.fun/posts/butterfly-custom/#%E9%A6%96%E9%A1%B5%E6%96%87%E7%AB%A0%E8%BD%AE%E6%92%AD%E6%A8%A1%E5%9D%97">我的Blog美化日记——Hexo+Butterfly | Guo Le’s Blog</a> 里面的“volantis”部分，和这个<a href="https://www.huangshiqing.website/2022/11/03/HexoTagPlugins/">Hexo Built-in Tag Plugins (Hexo内置标签外挂) | Ofra Serendipity</a></li><li>[ ] <strong>综合考虑是否需要将所有的图片转移到国内的图床中，比如阿里云的OSS</strong>。</li><li>[ ] 学习并在博客中添加图表-对于本网站以chartjs的图表为主，涉及UML就用Mermaid,对于精致的图表(比如数据分析)才会用Echart.</li><li>[ ] 添加RSS订阅</li><li>[ ] 把网站图像改为自己的qq头像，这样在RSS订阅中会好看一点。</li></ul><h2 id="debug经验">debug经验</h2><p>目前由于butterfly的版本更新，导致以前的部分功能失效，建议<strong>先看官方文档，将对应过时的代码注释或者去除，没有的代码添加</strong>，然后再<strong>根据</strong>F12检查对应的板块，<strong>用前端的知识去搜查问题发生的地点和原因</strong>，然后再纠错。</p><h2 id="hexo框架更新">hexo框架更新</h2><p>参考此博客<a href="https://blog.zhheo.com/p/6d1f1f98.html">如何更新Hexo及插件的版本？如何更新主题版本？ | 张洪Heo (zhheo.com)</a></p><p>简单来说就是先进入博客根目录然后在终端输入<code>npm update</code> ，确保node.js包是最新版本。然后输入<code>npm outdated</code> 看哪些插件已经过时，可以更新。然后修改根目录的package.json文件，将对应插件名称所对应的版本号更改为要更新的版本号。再在终端输入<code>npm install --save</code> 开始更新hexo及其插件，通过<code>hexo version</code> 查看是否已经更新</p><h2 id="butterfly主题更新">butterfly主题更新</h2><blockquote><p>更新前记得留下blog快照</p></blockquote><p>官方文档：<a href="https://butterfly.js.org/posts/21cfbf15/">Butterfly 文檔(一) 快速開始 | Butterfly</a></p><p>从butterfly5.0.0版本开始，可以直接在hexo根目录下输入<code>npm update hexo-theme-butterfly</code></p><p>如果不行，就在你的博客/themes/butterfly 根目录下打开git bash并输入<code>git pull</code> 即可更新</p><p>建议以后更新博客直接在命令行输入<code>hexo cl;hexo g</code> 一键清除与生成，多个分号代表分别执行。</p><h3 id="魔改内容">魔改内容</h3><p>我主要是参考以下几个链接对hexo和butterfly博客魔改的，由于每一次主题更新都会导致原来魔改的地方失效，建议一年更新一次并保存备份，然后按照以下链接更新对应的魔改部分</p><ul><li><strong>在时间轴、标签和分类添加图表</strong>：<a href="https://blog.guole.fun/posts/18158/index.html">使用Charts插件给Butterfly增加统计图表 | Guo Le’s Blog</a></li><li><strong>界面美化</strong>：<a href="https://www.fomal.cc/posts/eec9786.html">博客魔改教程总结(一) | Fomalhaut🥝</a></li><li><strong>在首页添加轮播图</strong>：<a href="https://akilar.top/posts/8e1264d1/">Swiper Bar | Akilarの糖果屋</a></li><li><strong>加载动画</strong>：<a href="https://akilar.top/posts/3d221bf2/">Loading Animation | Akilarの糖果屋</a></li><li><strong>字体</strong>：<a href="https://www.ccjinblog.info/2025/01/24/2025_1/butterfly%E9%AD%94%E6%94%B9%E6%95%99%E7%A8%8B2/index.html">butterfly魔改教程（二） | 山花终将烂漫 </a>  目前使用的是jetbrains的字体(毕竟是程序猿，看着亲切( •̀ ω •́ )✧)</li><li><strong>侧边栏添加二维码</strong>：<a href="https://fe32.top/articles/hexo1618/index.html#%E6%AD%A5%E9%AA%A4">Hexo + Butterfly 侧边栏公众号 | 唐志远</a> 基本上就在自定义的那个blog\source\css\custom.css文件后面改对应的链接即可，可以适当改一下css的格式(比如我这里的就是235px)</li><li><strong>文章链接优化</strong>：<a href="https://blog.codejerry.cn/posts/hexomogai/index.html">hexo-butterfly魔改美化 | Yan Zhang’s blog</a> <strong>以后写文章的时候都要在front-matter 前</strong>加上<code>abbrlink: zidingyiwenzi</code> 如果不写就生成随机数字，注意要<strong>避免重名</strong></li><li><strong>版权美化卡片</strong>：<a href="https://blog.codejerry.cn/posts/hexomogai/index.html">hexo-butterfly魔改美化 | Yan Zhang’s blog</a> 参考此文章</li><li><strong>添加了雪花效果</strong>：<a href="https://blog.codejerry.cn/posts/hexomogai/index.html">hexo-butterfly魔改美化 | Yan Zhang’s blog</a></li></ul><h4 id="魔改加载动画">魔改加载动画</h4><p><a href="https://akilar.top/posts/3d221bf2/">Loading Animation | Akilarの糖果屋</a> 此作者基于旧版hexo修改，<strong>其第一步的loading.pug和补充内容中的loading-js.pug均在index.pug文件中添加，其他不变</strong></p><p>如果想要添加自定义的动画</p><ol><li>修改<code>[Blogroot]\themes\butterfly\layout\includes\loading\index.pug</code> 中语句，添加<code>when ..... include.. </code></li><li>然后在<code>[Blogroot]\themes\butterfly\layout\includes\loading\load_style\</code>目录下 添加对应与第一步同名的 .pug文件</li><li>修改<code>[Blogroot]\themes\butterfly\source\css\_layout\loading.styl</code>，同样添加对应的代码</li><li>在<code>[Blogroot]\themes\butterfly\source\css\_load_style\</code>目录下添加对应动画的.styl 文件</li><li>修改<code>[Blogroot]\_config.butterfly.yml</code>的<code>preloader</code>配置项，将<code>load_style:</code> 改成你要的部分</li></ol><h4 id="魔改字体">魔改字体</h4><p>参考此篇博客(部分地方过时)， <a href="https://jingzhi1208.github.io/2021/11/26/hexo-butterfly%E4%B8%BB%E9%A2%98%E4%B8%8B%E6%9B%B4%E6%8D%A2%E5%AD%97%E4%BD%93/">hexo butterfly主题下更换字体 | ZHI’S BLOG</a> ，思路就是打开blog\source 目录，在下面建立一个font文件夹，然后将字体放入此文件夹，再修改blog\source\css\custom.css 文件(按照博客方式写)即可。因为我魔改了，所以不能完全按照博客所说的直接调用另一个css文件，魔改参考 <a href="https://www.ccjinblog.info/2025/01/24/2025_1/butterfly%E9%AD%94%E6%94%B9%E6%95%99%E7%A8%8B2/index.html">butterfly魔改教程（二） | 山花终将烂漫 </a></p><h4 id="魔改页脚">魔改页脚</h4><p>主要参考的链接：<a href="https://blog.codejerry.cn/posts/hexomogai/index.html">hexo-butterfly魔改美化 | Yan Zhang’s blog</a></p><p>如果想要添加“推荐友链”或者修改“猜你想看”部分，在<code>[BlogRoot]/themes/butterfly/layout/includes/footer.pug</code> 部分按照<strong>路由</strong>或者<strong>网址</strong> 的格式修改(我的和原作者不同，尤其是推荐友链部分，我没有使用img标签而是用a)</p><p>如果想要添加徽章，在<a href="https://shields.io/">shields.io</a> 上生成一个。参考下图</p><p><img src="https://s2.loli.net/2025/06/01/wUzkhEe12MIioyR.png" alt="demo_blog_001.png"></p><h2 id="个人hexo博客更新">个人hexo博客更新</h2><blockquote><p>以下是我写博客过程中常用的一些配置和功能</p></blockquote><p><strong>标签和分类</strong>：在md文件开头的是配置部分，tags是标签(就是在文档末尾出现的几个按钮文字)，<strong>可以有很多个</strong>;categories是分类，建议将其分为大类，<strong>小类从属于大类</strong>。在首页中博客只显示发布日期，更新日期、分类和标签(第一个).</p><p>示例代码如下</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">tags:</span> </span><br><span class="line"> <span class="bullet">-</span> <span class="string">blog</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">测试</span></span><br><span class="line"> <span class="bullet">-</span> <span class="string">教程</span></span><br></pre></td></tr></table></figure><p><strong>部署</strong>：我是参考这个博客部署到vercel上的<a href="https://blog.csdn.net/2403_88683045/article/details/144502347">参考链接</a> 。注意一旦部署到新的服务器上都要更新valine上的leancloud上的安全中心-web安全域名</p><p><strong>评论功能</strong>：我设置的是twikoo静态评论控制</p><p>主要参考的教程</p><ul><li><p>如何将twikoo部署到vercel上：<a href="https://www.bilibili.com/video/BV1Re4y1H7g8/?share_source=copy_web&amp;vd_source=bb8dacb993f11c0e39f8147c98a2894c">23.butterfly配置twikoo评论系统</a></p></li><li><p>如何将twikoo部署到netlify上：<a href="https://www.boke360.cn/post/twikoo-netlify-deploy/">Twikoo Netlify部署方法及操作流程，给博客网站添加评论功能 </a></p></li><li><p><a href="https://twikoo.js.org/backend.html#netlify-%E9%83%A8%E7%BD%B2">官方文档</a></p></li><li><p><a href="https://thirdshire.com/twikoo-tutorial/">如何配置机器人</a></p></li><li><p><a href="https://www.bayunmoyu.com/posts/twikoo-usage-guide/">评论正常但是无法接收邮件的解决方法</a>  ,其实就是在vercel中将 Vercel Authentication 设置为 Disabled。</p></li><li><p><a href="https://blog.hxrch.top/posts/%E6%95%B0%E6%8D%AE%E8%BF%81%E7%A7%BB%E4%B9%8B%E4%BB%8E-waline-%E5%88%B0-twikoo/">解释各个配置项的作用</a> 博主还详细讲解了如何自定义邮件模板，非常有帮助。</p></li><li><p><a href="https://blog.csdn.net/kissradish/article/details/108447972">网易获取授权码的方法</a>  邮件提醒需要开启SMTP的功能</p></li></ul><p>建议设置暗号，也就是要在昵称中输入暗号，然后点击评论区的时候才会显示管理功能，比如常规的暗号就是<strong>admin</strong>。</p><p><strong>文章置顶功能</strong>：可以直接在文章的 <code>front-matter</code> 区域里添加 <code>sticky: 1</code> 属性来把这篇文章置顶。数值越大，置顶的优先级越大。</p><p><strong>文章加密功能</strong>：文章加密插件  <a href="https://polar-bear.eu.org/2023/07/21/ce-shi/">参考链接</a> 也许以后添加。</p><p><strong>博客撰写</strong>：</p><ol><li>hexo会自动给分级标题编号，不需要自己添加</li><li>不要给标点符号加标签或者是特性，容易出现显示问题。</li></ol><p><strong>图片方面</strong></p><ul><li><p>方法1(<strong>我的主流方法</strong>)：通过picgo图床在插入图片的时候实现上传并转为URL链接格式。参考<a href="https://www.bilibili.com/video/BV1ci4y1L7j8?vd_source=bb8dacb993f11c0e39f8147c98a2894c">教程</a></p><ul><li>可将picgo配置github、阿里云OSS等图床，<a href="http://xn--S-wg8a779bq4djwzdsa898byw7a.EE">目前我配置的是S.EE</a></li><li>我参考的主要教程是：<a href="https://blog.gardenwalk.moe/2025/12/06/smms-picgo/">https://blog.gardenwalk.moe/2025/12/06/smms-picgo/</a>  如果图片上传失败，更新一下picgo即可，但是我没有设置开机自启动，所以如果需要上传图像，请先统一命名之后，启动picgo和魔法再插入图像，就会自动上传并且转化为markdown的格式</li></ul></li><li><p>方法2-本地上传图片：参考此<a href="https://blog.csdn.net/weixin_43702620/article/details/118655308">链接</a> 简单来说就是在post文件夹内对应每一个md文件创建同名的文件夹，然后将图片放在里面，需要引用的时候就按照<code>![](./文件夹名/图片名.png</code> 进行引用。<strong>注意图片必须放在与md文件同名的文件夹下且不允许中文命名</strong>。</p></li><li><p>方法3：使用其他的图床网站如<a href="https://smms.app/">SMMS</a>。上传图片后，点击markdown格式就可以复制图片路径，再用markdown语法粘贴即可。</p></li></ul><p><strong>音乐</strong>：我使用的是网易云的平台，如果要修改就在自己设置的那个歌单中修改对应的歌曲即可。</p><p><strong>导航栏设置</strong>：在<code>_config.butterfly.yml</code> 文件中搜索menu, 注意格式要和下面的一样，可以自行设置。  图标（就是||后面的内容）在这里<a href="https://fontawesome.com/v4/icons/">Font Awesome Icons</a>_ 搜索然后复制class= &quot; 复制这里的内容&quot; 替代即可。</p><p><strong>系列文章</strong>：在文章的 front-matter 上<strong>添加参数 series</strong>，并给予一個标签</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&#123;% series %&#125;</span><br><span class="line">&#123;% series [series name] %&#125;</span><br></pre></td></tr></table></figure><p><strong>首页轮播</strong>：在文章的front-matter 上添加参数<code>swiper_index: 1</code> 数字越大越靠前。</p><p><strong>自定义URL</strong>：分享链接的时候如果标题是中文，就会出现分隔符中文的情况，参考<a href="https://blog.csdn.net/weixin_42464282/article/details/130982114">https://blog.csdn.net/weixin_42464282/article/details/130982114</a> 教你安装abbrlink插件并为每一个博客自定义URL链接，防止URL过长。</p><p><strong>hexo添加RSS订阅</strong>：主要参考以下教程</p><ul><li><a href="https://blog.osyb.cn/posts/wz-20/">Hexo 博客安装与配置 RSS 插件，轻松生成订阅源</a></li></ul><p>使用说明：</p><ol><li>在每一篇的md文件<strong>front matter之后，正文之前</strong>建议插入图像封面图片，格式为<code>![](图片链接)</code> 因为RSS阅读器一般默认将文章中的第一张图像作为封面。</li><li>在<code>_config.yml</code> 文件中添加以下内容。注意我在上述教程的基础上添加了icon，<strong>显示指定网站图标</strong>，这样在folo中展示订阅源的时候网站图标才能显示正确。</li></ol><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># RSS订阅配置</span></span><br><span class="line"><span class="comment"># type: 生成的订阅源类型，可选 atom 或 rss2。建议使用atom</span></span><br><span class="line"><span class="comment"># path: 生成的订阅源文件路径，默认 atom.xml 或 rss2.xml。</span></span><br><span class="line"><span class="comment"># limit: 输出的文章数量限制，0 表示不限制。</span></span><br><span class="line"><span class="comment"># hub: PubSubHubbub 地址，可留空。</span></span><br><span class="line"><span class="comment"># content: 是否在订阅源中包含全文，true 表示包含全文，false 仅包含摘要。</span></span><br><span class="line"><span class="comment"># icon: 指定网站图标,以URL的格式</span></span><br><span class="line"><span class="attr">feed:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">atom</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">atom.xml</span></span><br><span class="line">  <span class="attr">limit:</span> <span class="number">20</span></span><br><span class="line">  <span class="attr">hub:</span></span><br><span class="line">  <span class="attr">content:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">icon:</span> </span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">主要用于博客的更新通知公告,相关基础内容的讲解以及其他的一些细节</summary>
    
    
    
    <category term="blog" scheme="https://lloydkai.cn/categories/blog/"/>
    
    
    <category term="教程" scheme="https://lloydkai.cn/tags/%E6%95%99%E7%A8%8B/"/>
    
    <category term="blog" scheme="https://lloydkai.cn/tags/blog/"/>
    
    <category term="hexo" scheme="https://lloydkai.cn/tags/hexo/"/>
    
  </entry>
  
</feed>
