-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
126 lines (74 loc) · 154 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>凉生</title>
<link href="/atom.xml" rel="self"/>
<link href="http://yoursite.com/"/>
<updated>2019-11-09T10:55:48.033Z</updated>
<id>http://yoursite.com/</id>
<author>
<name>凉生</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>ACM阶段复习</title>
<link href="http://yoursite.com/2019/11/09/ACM%E9%98%B6%E6%AE%B5%E5%A4%8D%E4%B9%A0/"/>
<id>http://yoursite.com/2019/11/09/ACM阶段复习/</id>
<published>2019-11-09T10:31:32.000Z</published>
<updated>2019-11-09T10:55:48.033Z</updated>
<content type="html"><![CDATA[<h3 id="1-C-C-循环输入"><a href="#1-C-C-循环输入" class="headerlink" title="1. C/C++ 循环输入"></a>1. C/C++ 循环输入</h3><a id="more"></a><h4 id="C"><a href="#C" class="headerlink" title="C++ :"></a><strong>C++ :</strong></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><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">int</span> a, b;</span><br><span class="line"><span class="keyword">while</span>(<span class="built_in">cin</span> >> a >> b) {</span><br><span class="line"> ...</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/--------------------------/</span><br><span class="line"><span class="built_in">cin</span> 是 C++ 的标准输入流,其本身是一个对象,并不存在返回值的概念。</span><br><span class="line"></span><br><span class="line">不过经常会有类似于</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span>(<span class="built_in">cin</span> >> a) 的调用,这里并不是 <span class="built_in">cin</span> 的返回值,而是 >> 操作重载函数</span><br><span class="line">istream& <span class="keyword">operator</span>>>(istream&, T &);的返回值,其中第二个参数由<span class="built_in">cin</span>>>后续参数类型决定</span><br><span class="line"></span><br><span class="line">其返回值类型为 istream& 类型,大多数情况下其返回值为 <span class="built_in">cin</span> 本身(非 <span class="number">0</span> 值)</span><br><span class="line">只有当遇到 EOF 输入或者复制失败时时,返回值为 <span class="number">0</span></span><br><span class="line"></span><br><span class="line">/-------------------------/</span><br><span class="line"> </span><br><span class="line"><span class="built_in">cin</span> 是 C++ 编程语言中的标准输入流对象,即 istream 类的对象。<span class="built_in">cin</span> 主要用于从标准输入读取数据,这里的标准输入,指的是</span><br><span class="line">终端的键盘。</span><br><span class="line">此外,<span class="built_in">cout</span> 是流的对象,即 ostream 类的对象</span><br><span class="line"></span><br><span class="line">/-------------------------/</span><br><span class="line">对象就是把 “类” 实例化 ,也类似于结构体变量的声明,它的创建格式是 类名+对象名,比如有一个已经定义的类 A ,可以这样把A实例化 A a ; a就是你创建的对象。只有创建了对象,类才能发挥作用。</span><br></pre></td></tr></table></figure><h4 id="C语言"><a href="#C语言" class="headerlink" title="C语言 :"></a><strong>C语言 :</strong></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><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="keyword">int</span> a, b;</span><br><span class="line"><span class="keyword">while</span>(<span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &a, &b) != EOF) {</span><br><span class="line"> ...</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/-------------------------/</span><br><span class="line"> </span><br><span class="line"><span class="number">1.</span> C 语言中 EOF 是什么意思?</span><br><span class="line"></span><br><span class="line">(<span class="number">1</span>)EOF 是 end of file 的缩写,表示 <span class="string">"文字流"</span>(stream)的结尾。这里的 <span class="string">"文字流"</span> ,可以是文件(file),</span><br><span class="line">也可以是标准输入。该宏定义在 stdio.h 中。</span><br><span class="line"></span><br><span class="line">(<span class="number">2</span>)EOF 不是特殊字符,而是一个定义在头文件 stdio.h 的常量,一般等于 <span class="number">-1</span></span><br><span class="line"> <span class="meta">#<span class="meta-keyword">define</span> EOF (-1)</span></span><br><span class="line"></span><br><span class="line">(<span class="number">3</span>)除了表示文件结尾,EOF 还可以表示标准输入的结尾。但是,标准输入与文件不一样,无法事先知道输入的长度,必</span><br><span class="line">须手动输入一个字符,表示到达 EOF。</span><br><span class="line"></span><br><span class="line">(<span class="number">4</span>)在 <span class="keyword">while</span> 循环中以 EOF 作为文件结束标志,这种以 EOF 作为文件结束标志的文件,必须是文本文件。</span><br><span class="line">在文本文件中,数据都是以字符的 ASCII 代码值的形式存放。</span><br><span class="line">我们知道,ASCII 代码值的范围是 <span class="number">0</span>~<span class="number">127</span>,不可能出现<span class="number">-1</span>,因此可以用 EOF 作为文件结束标志。 </span><br><span class="line">当读一个文件读到文件最后时,读文件的函数(比如函数fgetc(FILE *fp))就会返回这个常量。</span><br><span class="line">比如常用函数<span class="built_in">scanf</span>(),返回成功读入的数据个数,如果没有任何数据被成功读入,则返回 EOF。</span><br><span class="line"></span><br><span class="line">/---------------------------/</span><br><span class="line"></span><br><span class="line"><span class="number">2.</span> 头文件一般由四部分内容组成:</span><br><span class="line">(<span class="number">1</span>) 头文件开头处的版权和版本声明;</span><br><span class="line">(<span class="number">2</span>) 预处理块;</span><br><span class="line">(<span class="number">3</span>) <span class="keyword">inline</span> 函数的定义;</span><br><span class="line">(<span class="number">4</span>) 函数和类结构声明等。 ***</span><br><span class="line">在头文件中,用 ifndef/define/endif 结构产生预处理块,用 <span class="meta">#<span class="meta-keyword">include</span> 格式来引用库的头文件。头文件的这种结构,</span></span><br><span class="line">是利用 C 语言进行开发软件所通常具备的,属于公有知识</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><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="keyword">int</span> a, b;</span><br><span class="line"><span class="keyword">while</span>(~<span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &a, &b)) {</span><br><span class="line"> ...</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">/----------------------------/</span><br><span class="line"> <span class="number">-1</span> 的补码: <span class="number">11111111</span></span><br><span class="line"> 按位取反后: <span class="number">00000000</span> (即为假)</span><br><span class="line"> </span><br><span class="line"> 其它输入情况下(无论是否输入成功) <span class="keyword">while</span>循环的判断条件为非<span class="number">0</span> 即为真</span><br><span class="line"></span><br><span class="line">/----------------------------/</span><br><span class="line"> </span><br><span class="line"><span class="built_in">scanf</span>函数返回的是成功读入的个数</span><br><span class="line"></span><br><span class="line">如果只有a被成功读入,返回值为<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">如果a和b都未被成功读入,返回值为<span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">Windows下可以通过 Ctrl+z 或者 Ctrl+d 结束循环输入</span><br></pre></td></tr></table></figure><h3 id="2-t-组样例输入"><a href="#2-t-组样例输入" class="headerlink" title="2. t 组样例输入"></a>2. t 组样例输入</h3><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="keyword">int</span> t;</span><br><span class="line"><span class="built_in">cin</span> >> t;</span><br><span class="line"><span class="keyword">while</span>(t--) {</span><br><span class="line"> ...</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="3-double下不能-直等"><a href="#3-double下不能-直等" class="headerlink" title="3. double下不能 直等"></a>3. double下不能 直等</h3><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="keyword">double</span> a = <span class="number">5.3</span>;</span><br><span class="line"><span class="keyword">double</span> b = <span class="number">2.6</span> + <span class="number">2.7</span>; <span class="comment">//相加时会丢失精度</span></span><br><span class="line"></span><br><span class="line">结果:a != b</span><br><span class="line"></span><br><span class="line"> 符号位 指数位 尾数位</span><br><span class="line"><span class="keyword">float</span>: <span class="number">1</span> <span class="number">8</span> <span class="number">23</span> (bit)</span><br><span class="line"><span class="keyword">double</span>: <span class="number">1</span> <span class="number">11</span> <span class="number">52</span> (bit)</span><br></pre></td></tr></table></figure><h3 id="4-C-语言-double-类型的-printf-问题"><a href="#4-C-语言-double-类型的-printf-问题" class="headerlink" title="4. C 语言 double 类型的 printf 问题"></a>4. C 语言 double 类型的 printf 问题</h3><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">结论:在C语言中,<span class="keyword">double</span> 类型的读入必须用 <span class="string">"%lf"</span> ;输出要用 <span class="string">"%f"</span> ,但是 <span class="string">"%lf"</span> 也不错</span><br><span class="line"></span><br><span class="line">解释:<span class="keyword">double</span> 和 <span class="keyword">float</span> 的精度是不同的,故存储空间也是不同的,所以如果要读入 <span class="keyword">double</span> 类型,必须要用 %lf 来读入,</span><br><span class="line">以免精度丢失。而输出,由于 <span class="built_in">printf</span> 中并无对 %lf 的严格定义,故使用 %lf 不一定会出现正确结果。那使用 %f 输出又如</span><br><span class="line">何呢?由于 C 语言中的默认参数提升规则,%f 输出的不论是 <span class="keyword">float</span> 还是 <span class="keyword">double</span> 都会被提升到双精度进行输出,并不会有</span><br><span class="line">精度丢失。</span><br></pre></td></tr></table></figure><h3 id="5-最大公约数"><a href="#5-最大公约数" class="headerlink" title="5. 最大公约数"></a>5. 最大公约数</h3><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="comment">// 1. 递归版</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">gcd</span><span class="params">(<span class="keyword">int</span> a, <span class="keyword">int</span> b)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(b == <span class="number">0</span>) <span class="keyword">return</span> a;</span><br><span class="line"> <span class="keyword">return</span> gcd(b, a % b);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> a, b;</span><br><span class="line"> <span class="built_in">cin</span> >> a >> b;</span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"最大公约数是: "</span> << gcd(a, b) << <span class="built_in">endl</span>;</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"></span><br><span class="line"><span class="comment">// 2. 循环版</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> a, b;</span><br><span class="line"> <span class="built_in">cin</span> >> a >> b;</span><br><span class="line"> <span class="keyword">int</span> r = a % b;</span><br><span class="line"> <span class="keyword">while</span>(r != <span class="number">0</span>) {</span><br><span class="line"> a = b;</span><br><span class="line"> b = r;</span><br><span class="line"> r = a % b;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"最大公约数是: "</span> << b << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="6-冒泡排序"><a href="#6-冒泡排序" class="headerlink" title="6. 冒泡排序"></a>6. 冒泡排序</h3><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.从a[1]开始存</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"><span class="keyword">int</span> a[<span class="number">105</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">cin</span> >> n;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> a[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i < n; i++) {</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> j = <span class="number">1</span>; j <= n - i; j++) {</span><br><span class="line"> <span class="keyword">if</span>(a[j] > a[j + <span class="number">1</span>]) swap(a[j], a[j + <span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cout</span> << a[i] << <span class="string">' '</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">cout</span> << <span class="built_in">endl</span>;</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"></span><br><span class="line"><span class="comment">// 2.从a[0]开始存</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"><span class="keyword">int</span> a[<span class="number">105</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">cin</span> >> n;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> a[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < n - <span class="number">1</span>; i++) {</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> j = <span class="number">0</span>; j < n - i - <span class="number">1</span>; j++) {</span><br><span class="line"> <span class="keyword">if</span>(a[j] > a[j + <span class="number">1</span>]) {</span><br><span class="line"> <span class="keyword">int</span> t = a[j];</span><br><span class="line"> a[j] = a[j + <span class="number">1</span>];</span><br><span class="line"> a[j + <span class="number">1</span>] = t;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < n; i++) {</span><br><span class="line"> <span class="built_in">cout</span> << a[i] << <span class="string">' '</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">cout</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="7-二分"><a href="#7-二分" class="headerlink" title="7. 二分"></a>7. 二分</h3><p><strong>求根号x (保留4位小数)</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cmath></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">double</span> l = <span class="number">0</span>, r = n;</span><br><span class="line"> <span class="keyword">while</span>(l < r) {</span><br><span class="line"> <span class="keyword">double</span> mid = (l + r) / <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">abs</span>(mid * mid - n) <= <span class="number">1e-5</span>) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%.4lf\n"</span>, mid);</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"> <span class="keyword">if</span>(mid * mid > n) r = mid;</span><br><span class="line"> <span class="keyword">else</span> l = mid;</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></pre></td></tr></table></figure><h3 id="8-贪心"><a href="#8-贪心" class="headerlink" title="8. 贪心"></a>8. 贪心</h3><h4 id="例题-洛谷-P1007-独木桥"><a href="#例题-洛谷-P1007-独木桥" class="headerlink" title="例题 : 洛谷 P1007 独木桥"></a>例题 : <strong><a href="https://www.luogu.org/problem/P1007" target="_blank" rel="noopener">洛谷 P1007 独木桥</a></strong></h4><h3 id="9-博弈论"><a href="#9-博弈论" class="headerlink" title="9. 博弈论"></a>9. 博弈论</h3>]]></content>
<summary type="html">
<h3 id="1-C-C-循环输入"><a href="#1-C-C-循环输入" class="headerlink" title="1. C/C++ 循环输入"></a>1. C/C++ 循环输入</h3>
</summary>
<category term="Life isn't about waiting for the storm to pass, it's about learning to dance in the rain。生活不是等待暴风雨过去,而是要学会在雨中跳舞。" scheme="http://yoursite.com/tags/Life-isn-t-about-waiting-for-the-storm-to-pass-it-s-about-learning-to-dance-in-the-rain%E3%80%82%E7%94%9F%E6%B4%BB%E4%B8%8D%E6%98%AF%E7%AD%89%E5%BE%85%E6%9A%B4%E9%A3%8E%E9%9B%A8%E8%BF%87%E5%8E%BB%EF%BC%8C%E8%80%8C%E6%98%AF%E8%A6%81%E5%AD%A6%E4%BC%9A%E5%9C%A8%E9%9B%A8%E4%B8%AD%E8%B7%B3%E8%88%9E%E3%80%82/"/>
</entry>
<entry>
<title>Tarjan 求割点,桥(割边)</title>
<link href="http://yoursite.com/2019/10/29/Tarjan-%E6%B1%82%E5%89%B2%E7%82%B9-%E6%A1%A5-%E5%89%B2%E8%BE%B9/"/>
<id>http://yoursite.com/2019/10/29/Tarjan-求割点-桥-割边/</id>
<published>2019-10-29T09:18:18.000Z</published>
<updated>2019-10-29T11:00:01.460Z</updated>
<content type="html"><![CDATA[<h3 id="简介"><a href="#简介" class="headerlink" title="简介:"></a>简介:</h3><blockquote><p><strong>割边和割点的定义 <u>仅限于无向图</u> 中。我们可以通过定义以蛮力方式求解出无向图的所有割点和割边, 但这样的求解方式效率低。Tarjan 提出了一种快速求解的方式,通过一次 DFS 就求解出图中所有的割点和割边</strong></p></blockquote><a id="more"></a><h3 id="1-定义"><a href="#1-定义" class="headerlink" title="1. 定义"></a>1. 定义</h3><blockquote><p><strong>割点:</strong>无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点</p><p><strong>桥 (割边):</strong>无向联通图中,去掉一条边,图中的连通分量数增加,则这条边,称为桥或者割边</p></blockquote><h4 id="割点与桥(割边)的关系:"><a href="#割点与桥(割边)的关系:" class="headerlink" title="割点与桥(割边)的关系:"></a><strong>割点与桥(割边)的关系</strong>:</h4><p><strong>1)有割点不一定有桥, 有桥一定存在割点</strong></p><p><strong>2)桥一定是割点依附的边</strong></p><h3 id="2-Tarjan算法的原理"><a href="#2-Tarjan算法的原理" class="headerlink" title="2. Tarjan算法的原理"></a>2. Tarjan算法的原理</h3><p><strong>判断一个顶点是不是割点除了从定义,还可以从DFS(深度优先遍历)的角度出发</strong></p><p><strong>我们先通过 DFS 定义两个概念</strong></p><p>假设 DFS 中我们从 顶点U 访问到了 顶点V ( 此时 顶点V 还未被访问过 ), 那么我们称 顶点U 为 顶点V 的 <strong>父顶点</strong>,V 为 U 的 <strong>孩子顶点</strong>。在 顶点U 之前被访问过的顶点,我们就称之为 U 的 <strong>祖先顶点</strong></p><p>显然如果 顶点U 的 <u><strong>所有孩子顶点</strong></u> 可以不通过 父顶点U 而访问到 U 的祖先顶点,那么说明此时去掉 顶点U 不影响图的连通性,U就不是割点。相反,<u><strong>如果 顶点U 至少存在一个孩子顶点</strong></u>,必须通过 父顶点U 才能访问到 U 的祖先顶点,那么去掉 顶点U 后,顶点U 的祖先顶点和孩子顶点就不连通了,说明 U 是一个<strong>割点</strong>。</p><p><img src="https://ning2510.github.io/images/1.png" alt></p><p><strong>上图中的箭头表示 DFS 访问的顺序(而不表示有向图),对于 顶点D 而言,D 的孩子顶点可以通过连通 区域1 红色的边回到 D 的祖先 顶点C(此时 C 已被访问过),所以此时 D 不是割点</strong></p><p><img src="https://ning2510.github.io/images/2.png" alt></p><p>上图中的连通 区域2 中的顶点,<u><strong>必须通过 D 才能访问到 D 的祖先顶点</strong></u>,所以说此时 D 为割点。再次强调一遍,<u><strong>箭头仅仅表示 DFS 的访问顺序</strong></u>,而不是表示该图是有向图。</p><p>这里我们还需要考虑一个特殊情况,就是 DFS 的根顶点(一般情况下是编号为0的顶点),因为根顶点没有祖先顶点。其实根顶点是不是割点也很好判断,如果从根顶点出发,一次 DFS 就能访问到所有的顶点,那么根顶点就不是割点。反之,如果回溯到根顶点后,还有未访问过的顶点,需要在邻接顶点上再次进行 DFS,根顶点就是割点。 <strong><u>(简单来所就是若根顶点的有大于等于 2 个孩子,则根顶点就是割点)</u></strong></p><h3 id="3-Tarjan算法的实现细节"><a href="#3-Tarjan算法的实现细节" class="headerlink" title="3. Tarjan算法的实现细节"></a>3. Tarjan算法的实现细节</h3><h4 id="1-DFN数组"><a href="#1-DFN数组" class="headerlink" title="1. DFN数组"></a>1. DFN数组</h4><blockquote><p><strong>DFN[i]: 表示该顶点 i 在DFS中的遍历顺序(或者说时间戳)</strong></p></blockquote><p><strong>注意: 我们 DFS 遍历时总是先遍历节点编号小的, 再遍历节点编号大的</strong></p><p>每访问到一个未访问过的顶点,访问顺序的值(时间戳)就增加1。<strong>子顶点的 DFN 值一定比父顶点的 DFN 值大</strong>(但不一定恰好大 1,比如父顶点有两个及两个以上分支的情况)。在访问一个顶点后,它的 DFN 的值就确定下来了,不会再改变。</p><h4 id="2-LOW数组"><a href="#2-LOW数组" class="headerlink" title="2. LOW数组"></a>2. LOW数组</h4><blockquote><p><strong>LOW[i]: 表示 DFS 中顶点 i <u>不通过</u> 父顶点能访问到的祖先顶点中最小的顺序值(或者说时间戳, 也可以说是 DFN值)</strong></p></blockquote><h4 id="3-实现过程"><a href="#3-实现过程" class="headerlink" title="3. 实现过程"></a>3. 实现过程</h4><p><strong>思想体现 :</strong></p><ul><li><strong>对于根节点: 计算其子树数量,如果有 2 棵即以上的子树,就是割点。因为如果去掉这个点,这两棵子树就不能互相到达。</strong></li><li><strong>对于非根节点: 对于边(u, v),如果 LOW[v]>=DFN[u],此时 u 就是割点。</strong></li><li><strong>每个顶点初始的 LOW 值和 DFN 值应该一样 (即最早只能回溯到自身)</strong></li></ul><p><strong>在 DFS 中,我们根据情况不断更新 LOW 的值。</strong></p><p><strong>有一条边 (u, v), 如果 v 未访问过, 继续 DFS, DFS完之后, LOW[u]=min(LOW[u], LOW[v]);</strong></p><p><strong>如果 v 访问过(且 u 不是 v 的父亲) , 就不需要继续 DFS 了,一定有 DFN[v] < DFN[u],LOW[u]=min(LOW[u], DFN[v])</strong></p><p><strong>下面观点来自某位大佬 : (仅供参考理解)</strong></p><blockquote><p><strong>关于 Tarjan 算法,一直有一个很大的争议,就是 LOW[u]=min(LOW[u], DFN[v]);</strong></p><p><strong>这句话,如果改成 LOW[u]=min(LOW[u], LOW[v]) 就会wa掉,但是在求强连通分量时却没有问题</strong></p><p><strong>根据许多大佬的观点,我想提出自己的一点看法,在求强连通分量时,如果 v 已经在栈中,那么说明 u, v 一定在同一个强连通分量中,所以到最后 LOW[u]=LOW[v] 是必然的,提前更新也不会有问题,但是在求割点时,LOW的定义有了小小的变化,不再是最早能追溯到的祖先,(因为是个无向图)没有意义,应该是最早能绕到的割点,为什么用绕到,是因为是无向边,所以有另一条路可以走,如果把 DFN[v] 改掉就会上翻过头,可能翻进另一个环中,所以 WA 掉,仅是本人的一些个人看法,不知道讲的对不对,请各位指教。</strong></p></blockquote><p><strong>不明白的话看完代码, 画两个环, 手动推一下就明白了~</strong></p><p><strong>来看一个具体的例子 :</strong></p><p><strong>模仿程序计算各个顶点的 DFN 值和 LOW 值。下图中 <u>蓝色实线箭头表示已访问过的路径,无箭头虚线表示未访问路径。已访问过的顶点用黄色标记,未访问的顶点用白色标记,DFS 当前正在处理的顶点用绿色表示。带箭头的蓝色虚线表示 DFS 回溯时的返回路径</u>。</strong></p><p><strong>1.</strong></p><p><img src="https://ning2510.github.io/images/3.png" alt></p><p>当 DFS 走到 顶点H 时,有三个分支,<strong>按照遍历顺序(总是先走编号小的节点), 先走 H-I,然后走 H-F,最后走 H-J</strong>, 从 H 访问 I 时,顶点I 未被访问过,所以I的 DFN 和 LOW 都为 9。根据 DFS 的遍历顺序,我们应该从顶点I继续访问。</p><p><strong>2.</strong></p><p><img src="https://ning2510.github.io/images/4.png" alt></p><p><strong>上图表示由 顶点I 访问 顶点D,而此时发现 D 已被访问,当从 D 回溯到 I 时,由于</strong></p><p><strong>DFN[D] < DFN[I]</strong></p><p><strong>说明 D 是 I 的祖先顶点,所以到现在为止,顶点I 不经过 父顶点H 能访问到的小时间戳为 4</strong></p><p><strong>3.</strong></p><p><img src="https://ning2510.github.io/images/5.png" alt></p><p><strong>根据 DFS 的原理,我们从 顶点I 回到 顶点H,显然到目前为止 顶点H 能访问到的最小时间戳也是 4(因为我们到现在为止只知道能从 H 可以通过 I 访问到 D ),所以 LOW[H] = 4</strong></p><p><strong>4.</strong></p><p><img src="https://ning2510.github.io/images/6.png" alt></p><p><strong>现在我们继续执行 DFS,走 H-F 路径,发现 顶点F 已被访问且 DFN[F] < DFN[H],说明 F 是 H 的祖先顶点,但此时 顶点H 能访问的最早时间戳是 4,而 F 的时间戳是 6,依据 LOW 值定义 LOW[H] 仍然为 4</strong></p><p><strong>5.</strong></p><p><img src="https://ning2510.github.io/images/7.png" alt></p><p><strong>最后我们走 H-J 路径,顶点J 未被访问过所以 DFN[J] = 10 LOW[J] = 10</strong></p><p><strong>6.</strong></p><p><img src="https://ning2510.github.io/images/8.png" alt></p><p><strong>同理,由 DFS 访问 顶点B,DFN[J] > DFN[B],B为祖先顶点,顶点J 不经过 父顶点H 能访问到的最早时间戳就是 DFN[B],即 LOW[J] = 2</strong></p><p><strong>7.</strong></p><p><img src="https://ning2510.github.io/images/9.png" alt></p><p><strong>我们从 顶点J 回溯到 顶点H,显然到目前为止顶点H能访问到的最早时间戳就更新为 2(因为我们到现在为止知道了能从 H 访问到 J ),所以 LOW[H] = 2</strong></p><p><strong>8.</strong></p><p><img src="https://ning2510.github.io/images/10.png" alt></p><p><strong>根据 DFS 原理,我们从 H 回退到 顶点E( H回退到G, G回退到F,F回退到E 的过程省略),所经过的顶点都会更新 LOW 值,因为这些顶点不用通过自己的父顶点就可以和 顶点B 相连。当回溯到 顶点E 时,还有未访问过的顶点,那么继续进行 E-K 分支的 DFS</strong></p><p><strong>9.</strong></p><p><img src="https://ning2510.github.io/images/11.png" alt></p><p><strong>从 E-K 分支访问到 顶点L 时,顶点K 和 L 的 DFN值 和 LOW值 如上图所示</strong></p><p><strong>10.</strong></p><p><img src="https://ning2510.github.io/images/12.png" alt></p><p><strong>接着我们继续回溯到了 顶点D(中间过程有所省略),并更新 LOW[D]</strong></p><p><strong>11.</strong></p><p><img src="https://ning2510.github.io/images/13.png" alt></p><p><strong>最后,按照 DFS 的原理,我们回退到 顶点A,并且求出来了每个顶点的 DFN值 和 LOW值</strong></p><h4 id="4-割点-和-桥-割边-的判定方法"><a href="#4-割点-和-桥-割边-的判定方法" class="headerlink" title="4. 割点 和 桥(割边) 的判定方法"></a>4. 割点 和 桥(割边) 的判定方法</h4><ul><li><strong>割点 :</strong> </li></ul><p><strong>1) 对于根节点 : 若根节点的孩子数大于等于2, 则 根节点为割点</strong></p><p><strong>2) 对于非根节点 : 对于边 (u, v), 若 LOW[v] >= DFN[u] ,则点 u 为割点</strong></p><p><strong>( 若 LOW[V] >= DFN[u] 就说明顶点V访问顶点U的祖先顶点,必须通过顶点U,而不存在顶点V到顶点U祖先顶点的其它路径,所以顶点U就是一个割点 )</strong></p><ul><li><strong>桥 (割边) :</strong></li></ul><p><strong>对于边 (u, v), 若 LOW[v] > DFN[u], 则 u -> v 这条边为桥 ( 因为不包含节点u )</strong> </p><blockquote><p><strong>需要说明的是: Tarjan 算法从图的任意顶点进行 DFS 都可以得出割点集和割边集</strong></p></blockquote><h3 id="4-割点代码实现"><a href="#4-割点代码实现" class="headerlink" title="4. 割点代码实现"></a>4. 割点代码实现</h3><p><strong>以 <a href="https://www.luogu.org/problem/P3388" target="_blank" rel="noopener">洛谷 P3388</a> 为例</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><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="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> maxn = <span class="number">1e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n, m, num_edge, t;</span><br><span class="line"><span class="keyword">int</span> head[maxn], DFN[maxn], LOW[maxn];</span><br><span class="line"><span class="keyword">bool</span> vis[maxn];</span><br><span class="line"><span class="comment">//DFN[i]:就是时间戳,即在什么时刻搜索到了点i</span></span><br><span class="line"><span class="comment">//LOW[i]:则是i点能回溯到的DFN最小的祖先</span></span><br><span class="line"><span class="comment">/*如果一条边满足low[v]>=dfn[u],那么u点即为一个割点. </span></span><br><span class="line"><span class="comment">证明:如果存在这样一条边满足这样的性质,那么u的儿子v就永远不会访问到早于u的点,那么也就是说,从v出发形成的环中不会包括u,那么从u断开的话,就会形成两个或多个连通块,满足了割点的需求.*/</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">stu</span> {</span></span><br><span class="line"> <span class="keyword">int</span> to, nex;</span><br><span class="line">}edge[maxn], ans[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">addedge</span><span class="params">(<span class="keyword">int</span> from, <span class="keyword">int</span> to)</span> </span>{</span><br><span class="line"> edge[++num_edge].to = to;</span><br><span class="line"> edge[num_edge].nex = head[from];</span><br><span class="line"> head[from] = num_edge;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">tarjan</span><span class="params">(<span class="keyword">int</span> u, <span class="keyword">int</span> fa)</span> </span>{</span><br><span class="line"> DFN[u] = LOW[u] = ++t;</span><br><span class="line"> <span class="keyword">int</span> child = <span class="number">0</span>; <span class="comment">//以fa为根的子树0的个数</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = head[u]; i; i = edge[i].nex) {</span><br><span class="line"> <span class="keyword">int</span> v = edge[i].to;</span><br><span class="line"> <span class="keyword">if</span>(!DFN[v]) {</span><br><span class="line"> tarjan(v, fa);</span><br><span class="line"> LOW[u] = min(LOW[u], LOW[v]); <span class="comment">//更新当前节点的low值</span></span><br><span class="line"> <span class="keyword">if</span>(u != fa && LOW[v] >= DFN[u]) vis[u] = <span class="number">1</span>;</span><br><span class="line"> <span class="comment">//如果一个点不是根,并且它的儿子在不经过它的情况下无法回到它的父亲,那么它也是割点</span></span><br><span class="line"> <span class="keyword">if</span>(u == fa) child++;</span><br><span class="line"> }</span><br><span class="line"> LOW[u] = min(LOW[u], DFN[v]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(child >= <span class="number">2</span> && u == fa) vis[u] = <span class="number">1</span>;</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="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &n, &m);</span><br><span class="line"> <span class="keyword">int</span> x, y;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &x, &y);</span><br><span class="line"> addedge(x, y);</span><br><span class="line"> addedge(y, x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) { <span class="comment">//图可能不连通</span></span><br><span class="line"> <span class="keyword">if</span>(!DFN[i]) tarjan(i, i);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(vis[i]) ans++;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, ans);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(vis[i]) <span class="built_in">printf</span>(<span class="string">"%d "</span>, i);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"\n"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="5-桥-割边-代码实现"><a href="#5-桥-割边-代码实现" class="headerlink" title="5. 桥 (割边) 代码实现"></a>5. 桥 (割边) 代码实现</h3><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><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/*注意:</span></span><br><span class="line"><span class="comment">若建图后的第i条边为: u -> v</span></span><br><span class="line"><span class="comment">则 第i^1条边为: v -> u</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="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> maxn = <span class="number">1e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n, m, t, num_edge;</span><br><span class="line"><span class="keyword">int</span> head[maxn], DFN[maxn], LOW[maxn];</span><br><span class="line"><span class="keyword">bool</span> vis[maxn];</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">stu</span> {</span></span><br><span class="line"> <span class="keyword">int</span> to, nex;</span><br><span class="line">}edge[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">addedge</span><span class="params">(<span class="keyword">int</span> from, <span class="keyword">int</span> to)</span> </span>{</span><br><span class="line"> edge[++num_edge].to = to;</span><br><span class="line"> edge[num_edge].nex = head[from];</span><br><span class="line"> head[from] = num_edge;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">tarjan</span><span class="params">(<span class="keyword">int</span> u, <span class="keyword">int</span> Edge)</span> </span>{ <span class="comment">//Edge:当前是第几条边 u:当前边的儿子节点</span></span><br><span class="line"> DFN[u] = LOW[u] = ++t; <span class="comment">////DFS序标记</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = head[u]; i; i = edge[i].nex) { <span class="comment">////访问所有出边</span></span><br><span class="line"> <span class="keyword">int</span> v = edge[i].to; <span class="comment">//出边</span></span><br><span class="line"> <span class="keyword">if</span>(!DFN[v]) { <span class="comment">//不曾访问过,也就是没有标记,可以认为是儿子节点了 </span></span><br><span class="line"> tarjan(v, i); <span class="comment">//访问儿子节点v,并且设置边为当前边</span></span><br><span class="line"> LOW[u] = min(LOW[u], LOW[v]); <span class="comment">//这就是桥的判定</span></span><br><span class="line"> <span class="keyword">if</span>(LOW[v] > DFN[u]) vis[i] = vis[i ^ <span class="number">1</span>] = <span class="number">1</span>; <span class="comment">//重边也是桥</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(i != (Edge ^ <span class="number">1</span>)) LOW[u] = min(LOW[u], DFN[v]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &n, &m);</span><br><span class="line"> num_edge = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">int</span> x, y;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &x, &y);</span><br><span class="line"> addedge(x, y);</span><br><span class="line"> addedge(y, x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(!DFN[i]) tarjan(i, <span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">2</span>; i <= num_edge; i += <span class="number">2</span>) {</span><br><span class="line"> <span class="keyword">if</span>(vis[i]) <span class="built_in">printf</span>(<span class="string">"%d %d\n"</span>, edge[i ^ <span class="number">1</span>].to, edge[i].to);</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></pre></td></tr></table></figure><h4 id="例题"><a href="#例题" class="headerlink" title="例题 :"></a>例题 :</h4><p><strong><a href="https://www.luogu.org/problem/P1656" target="_blank" rel="noopener">洛谷 P1656</a></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><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"> </span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">int</span> maxn = <span class="number">1e6</span> + <span class="number">5</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n, m, t, num_edge;</span><br><span class="line"><span class="keyword">int</span> head[maxn], DFN[maxn], LOW[maxn];</span><br><span class="line"><span class="keyword">bool</span> vis[maxn];</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">stu</span> {</span></span><br><span class="line"> <span class="keyword">int</span> to, nex;</span><br><span class="line">}edge[maxn], ans[maxn];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">cmp</span><span class="params">(stu x, stu y)</span> </span>{</span><br><span class="line"> <span class="keyword">if</span>(x.to == y.to) <span class="keyword">return</span> x.nex < y.nex;</span><br><span class="line"> <span class="keyword">return</span> x.to < y.to;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">addedge</span><span class="params">(<span class="keyword">int</span> from, <span class="keyword">int</span> to)</span> </span>{</span><br><span class="line"> edge[++num_edge].to = to;</span><br><span class="line"> edge[num_edge].nex = head[from];</span><br><span class="line"> head[from] = num_edge;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">tarjan</span><span class="params">(<span class="keyword">int</span> u, <span class="keyword">int</span> Edge)</span> </span>{ <span class="comment">//Edge:当前是第几条边 u:当前边的儿子节点</span></span><br><span class="line"> DFN[u] = LOW[u] = ++t; <span class="comment">////DFS序标记</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = head[u]; i; i = edge[i].nex) { <span class="comment">////访问所有出边</span></span><br><span class="line"> <span class="keyword">int</span> v = edge[i].to; <span class="comment">//出边</span></span><br><span class="line"> <span class="keyword">if</span>(!DFN[v]) { <span class="comment">//不曾访问过,也就是没有标记,可以认为是儿子节点了 </span></span><br><span class="line"> tarjan(v, i); <span class="comment">//访问儿子节点v,并且设置边为当前边</span></span><br><span class="line"> LOW[u] = min(LOW[u], LOW[v]); <span class="comment">//这就是桥的判定</span></span><br><span class="line"> <span class="keyword">if</span>(LOW[v] > DFN[u]) vis[i] = vis[i ^ <span class="number">1</span>] = <span class="number">1</span>; <span class="comment">//重边也是桥</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span>(i != (Edge ^ <span class="number">1</span>)) LOW[u] = min(LOW[u], DFN[v]);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &n, &m);</span><br><span class="line"> num_edge = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">int</span> x, y;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d%d"</span>, &x, &y);</span><br><span class="line"> addedge(x, y);</span><br><span class="line"> addedge(y, x);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>(!DFN[i]) tarjan(i, <span class="number">0</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">int</span> tt = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">2</span>; i <= num_edge; i += <span class="number">2</span>) {</span><br><span class="line"> <span class="keyword">if</span>(vis[i]) {</span><br><span class="line"> ans[++tt].to = min(edge[i].to, edge[i ^ <span class="number">1</span>].to);</span><br><span class="line"> ans[tt].nex = max(edge[i].to, edge[i ^ <span class="number">1</span>].to);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> sort(ans + <span class="number">1</span>, ans + tt + <span class="number">1</span>, cmp);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= tt; i++) {</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d %d\n"</span>, ans[i].to, ans[i].nex);</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></pre></td></tr></table></figure><h4 id="6-参考网址"><a href="#6-参考网址" class="headerlink" title="6. 参考网址"></a>6. 参考网址</h4><p><strong><a href="https://www.cnblogs.com/nullzx/p/7968110.html" target="_blank" rel="noopener">传送门 1</a></strong></p><p><strong><a href="https://www.cnblogs.com/gzh-red/p/11253230.html#_lab2_1_0" target="_blank" rel="noopener">传送门 2</a></strong></p>]]></content>
<summary type="html">
<h3 id="简介"><a href="#简介" class="headerlink" title="简介:"></a>简介:</h3><blockquote>
<p><strong>割边和割点的定义 <u>仅限于无向图</u> 中。我们可以通过定义以蛮力方式求解出无向图的所有割点和割边, 但这样的求解方式效率低。Tarjan 提出了一种快速求解的方式,通过一次 DFS 就求解出图中所有的割点和割边</strong></p>
</blockquote>
</summary>
<category term="One today is worth two tomorrows. 一个今天胜似两个明天" scheme="http://yoursite.com/tags/One-today-is-worth-two-tomorrows-%E4%B8%80%E4%B8%AA%E4%BB%8A%E5%A4%A9%E8%83%9C%E4%BC%BC%E4%B8%A4%E4%B8%AA%E6%98%8E%E5%A4%A9/"/>
</entry>
<entry>
<title>字典树 (Trie 树)</title>
<link href="http://yoursite.com/2019/09/11/%E5%AD%97%E5%85%B8%E6%A0%91/"/>
<id>http://yoursite.com/2019/09/11/字典树/</id>
<published>2019-09-11T00:50:00.000Z</published>
<updated>2019-09-12T09:53:35.757Z</updated>
<content type="html"><![CDATA[<h3 id="1-引入"><a href="#1-引入" class="headerlink" title="1. 引入"></a>1. 引入</h3><p><strong>字典是干啥的?查找字的。</strong></p><a id="more"></a><p><strong>字典树自然也是起查找作用的。查找的是啥?单词。</strong></p><p><strong>看以下几个题:</strong></p><p><strong>1) 给出n个单词和m个询问,每次询问一个单词,回答这个单词是否在单词表中出现过。</strong></p><p><strong>答:简单!map,短小精悍。</strong></p><p><strong>好。下一个</strong></p><p><strong>2) 给出n个单词和m个询问,每次询问一个前缀,回答询问是多少个单词的前缀。</strong></p><p><strong>答:map,把每个单词拆开。</strong></p><p><strong>judge:n<=200000,TLE!</strong></p><p><strong>这就需要一种高级数据结构——Trie树(字典树)</strong></p><h3 id="2-原理"><a href="#2-原理" class="headerlink" title="2. 原理"></a>2. 原理</h3><p><strong>在本篇文章中,假设 <u>所有单词都只由小写字母</u> 构成</strong></p><p><strong>对cat,cash,app,apple,aply,ok 建一颗字典树,建成之后如下图所示</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/08/8921351f8b9b22a7.jpg" alt></p><p><strong>由此可以看出:</strong></p><p><strong>1、字典树用边表示字母</strong></p><p><strong>2、有相同前缀的单词公用前缀节点,那我们可以的得出每个节点最多有26个子节点(在单词只包含小写字母的情况下)</strong></p><p><strong>3、整棵树的根节点是空的。为什么呢?便于插入和查找,这将会在后面解释。</strong></p><p><strong>4、每个单词结束的时候用一个特殊字符表示,图中用的‘′,那么从根节点到任意一个‘′,那么从根节点到任意一个‘’所经过的边的所有字母表示一个单词。</strong></p><h3 id="3-基本操作"><a href="#3-基本操作" class="headerlink" title="3. 基本操作"></a>3. 基本操作</h3><h4 id="1-insert-插入一个单词"><a href="#1-insert-插入一个单词" class="headerlink" title="1. insert 插入一个单词"></a>1. insert 插入一个单词</h4><p><strong>思路:</strong></p><p> <strong>从图中可以直观看出,从左到右扫这个单词,如果字母在相应根节点下没有出现过,就插入这个字母;否则沿着字典树往下走,看单词的下一个字母。</strong></p><p> <strong>这就产生一个问题:往哪儿插?计算机不会自己选择位置插,我们需要给它指定一个位置,那就需要给每个字母编号。</strong></p><p> <strong>我们设数组trie[i][j]=k,表示<u>编号为i</u>的节点的<u>第j个</u>孩子是<u>编号为k</u>的节点。</strong></p><p> <strong>什么意思呢?</strong></p><p> <strong>这里有2种编号,一种是i,k表示节点的位置编号,这是相对整棵树而言的;另一种是j,表示节点i的第j的孩子,这是相对节点i而言的。</strong></p><p> <strong>不理解?看图</strong></p><p> <strong>还是单词cat,cash,app,apple,aply,ok</strong> </p><p> <strong>我们就按输入顺序对其编第一种号,红色表示编号结果。因为先输入的cat,所以c,a,t分别是1,2,3,然后输入的是cash,因为c,a是公共前缀,所以从s开始编,s是4,以此类推。</strong></p><p><strong>注意这里<u>相同字母的编号可能不同</u></strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/08/acf0e47d354d65b7.jpg" alt></p><p><strong>第二种编号,相对节点的编号,<u>紫色</u>表示编号结果。</strong></p><p><strong>因为每个节点最多有26个子节点,我们可以按他们的字典序从0——25编号,也就是他们的ASCLL码-a的ASCLL码。</strong></p><p><strong>注意这里<u>相同字母的编号相同</u></strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/08/c6068116e03e033b.jpg" alt></p><p><strong>实际上每个节点的子节点都应该从0编到——25,但这样会发现许多事根本用不到的。比如上图的根节点应该分出26个叉。节约空间,用到哪个分哪个。</strong></p><p> <strong>这样编号有什么用呢?</strong></p><p><strong>回到数组trie[i][j]=k。 数组trie[i][j]=k,表示编号为i的节点的第j个孩子是编号为k的节点。</strong></p><p><strong>那么第二种编号即为j,第一种编号即为i,k</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="function"><span class="keyword">void</span> <span class="title">insert</span><span class="params">()</span> </span>{<span class="comment">//插入单词s</span></span><br><span class="line"> len = <span class="built_in">strlen</span>(s);<span class="comment">//单词s的长度</span></span><br><span class="line"> root = <span class="number">0</span>;<span class="comment">//根节点编号为0</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++) {</span><br><span class="line"> <span class="keyword">int</span> id = s[i] - <span class="string">'a'</span>;<span class="comment">//第二种编号</span></span><br><span class="line"> <span class="keyword">if</span>(!trie[root][id])<span class="comment">//如果之前没有从root到id的前缀 </span></span><br><span class="line"> trie[root][id] = ++tot;<span class="comment">//插入,tot即为第一种编号</span></span><br><span class="line"> root = trie[root][id];<span class="comment">//顺着字典树往下走</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="2-search-查找"><a href="#2-search-查找" class="headerlink" title="2. search 查找"></a>2. search 查找</h4><p><strong>思路:</strong></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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">find</span><span class="params">()</span> </span>{</span><br><span class="line"> len = <span class="built_in">strlen</span>(s);</span><br><span class="line"> root = <span class="number">0</span>;<span class="comment">//从根结点开始找</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; s[i]; i++) {</span><br><span class="line"> <span class="keyword">int</span> x = s[i] - <span class="string">'a'</span>;<span class="comment">//</span></span><br><span class="line"> <span class="keyword">if</span>(trie[root][x] == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="comment">//以root为头结点的x字母不存在,返回0 </span></span><br><span class="line"> root = trie[root][x];<span class="comment">//为查询下个字母做准备,往下走 </span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;<span class="comment">//找到了</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>3、如果是查询某个单词的话,我们用bool变量 v[i]表示节点i是否是单词结束的标志。</strong></p><p> <strong>那么最后return的是v[root],所以在插入操作中插入完每个单词是,要对单词最后一个字母的v[i]置为true,其他的都是false</strong></p><p><strong>4、如果是查询前缀出现的次数的话,那就在开一个sum[],表示位置i被访问过的次数</strong></p><p> <strong>那么最后return的是sum[root],插入操作中每访问一个节点,都要让他的sum++</strong></p><p> <strong>这里前缀的次数是标记在前缀的最后一个字母所在位置的后一个位置上。</strong></p><p> <strong>比如:前缀abc出现的次数标记在c所在位置的后一个位置上</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/08/35b8132538bc8220.jpg" alt></p><h4 id="3-完整代码实现"><a href="#3-完整代码实现" class="headerlink" title="3. 完整代码实现"></a>3. 完整代码实现</h4><p><strong>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><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="comment">/*</span></span><br><span class="line"><span class="comment"> trie tree的储存方式:将字母储存在边上,边的节点连接与它相连的字母 </span></span><br><span class="line"><span class="comment"> trie[rt][x]=tot:rt是上个节点编号,x是字母,tot是下个节点编号 </span></span><br><span class="line"><span class="comment">*/</span> </span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> maxn 2000010</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> tot = <span class="number">1</span>, n;</span><br><span class="line"><span class="keyword">int</span> trie[maxn][<span class="number">26</span>];</span><br><span class="line"><span class="comment">//bool isw[maxn];查询整个单词用</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">insert</span><span class="params">(<span class="keyword">char</span> *s, <span class="keyword">int</span> rt)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; s[i]; i++) {</span><br><span class="line"> <span class="keyword">int</span> x = s[i] - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span>(trie[rt][x] == <span class="number">0</span>) { <span class="comment">//现在插入的字母在之前同一节点处未出现过 </span></span><br><span class="line"> trie[rt][x] = ++tot;<span class="comment">//字母插入一个新的位置,否则不做处理 </span></span><br><span class="line"> }</span><br><span class="line"> rt = trie[rt][x];<span class="comment">//为下个字母的插入做准备 </span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/*isw[rt] = true;标志该单词末位字母的尾结点,在查询整个单词时用到*/</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">bool</span> <span class="title">find</span><span class="params">(<span class="keyword">char</span> *s, <span class="keyword">int</span> rt)</span> </span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; s[i]; i++) {</span><br><span class="line"> <span class="keyword">int</span> x = s[i] - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span>(trie[rt][x] == <span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">//以rt为头结点的x字母不存在,返回0 </span></span><br><span class="line"> rt = trie[rt][x]; <span class="comment">//为查询下个字母做准备 </span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="comment">//查询整个单词时,应该return isw[rt] </span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">char</span> s[<span class="number">22</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> tot = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">int</span> rt = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> s;</span><br><span class="line"> insert(s, rt);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> s;</span><br><span class="line"> <span class="keyword">if</span>(find(s, rt)) <span class="built_in">printf</span>(<span class="string">"YES\n"</span>);</span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">printf</span>(<span class="string">"NO\n"</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></pre></td></tr></table></figure><p><strong>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><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstdio></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><algorithm></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> trie[<span class="number">400001</span>][<span class="number">26</span>], len, root, tot, sum[<span class="number">400001</span>];</span><br><span class="line"><span class="keyword">char</span> s[<span class="number">12</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">insert</span><span class="params">(<span class="keyword">char</span> *s)</span> </span>{</span><br><span class="line"> len = <span class="built_in">strlen</span>(s);</span><br><span class="line"> root = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++) {</span><br><span class="line"> <span class="keyword">int</span> id = s[i] - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span>(!trie[root][id]) trie[root][id] = ++tot;</span><br><span class="line"> sum[trie[root][id]]++; <span class="comment">//前缀保存 </span></span><br><span class="line"> root = trie[root][id];</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">search</span><span class="params">(<span class="keyword">char</span> *s)</span> </span>{</span><br><span class="line"> root = <span class="number">0</span>;</span><br><span class="line"> len = <span class="built_in">strlen</span>(s);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i < len; i++) {</span><br><span class="line"> <span class="keyword">int</span> id = s[i] - <span class="string">'a'</span>;</span><br><span class="line"> <span class="keyword">if</span>(!trie[root][id]) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> root = trie[root][id];</span><br><span class="line"> } <span class="comment">//root经过此循环后变成前缀最后一个字母所在位置</span></span><br><span class="line"> <span class="keyword">return</span> sum[root];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n, m;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">char</span> s[<span class="number">12</span>];</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &n);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> s;</span><br><span class="line"> insert(s);</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">scanf</span>(<span class="string">"%d"</span>, &m);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= m; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> s;</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"%d\n"</span>, search(s));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>参考网址: <a href="https://www.cnblogs.com/TheRoadToTheGold/p/6290732.html" target="_blank" rel="noopener">网址</a></strong></p>]]></content>
<summary type="html">
<h3 id="1-引入"><a href="#1-引入" class="headerlink" title="1. 引入"></a>1. 引入</h3><p><strong>字典是干啥的?查找字的。</strong></p>
</summary>
<category term="All things come to those who wait. 苍天不负有心人" scheme="http://yoursite.com/tags/All-things-come-to-those-who-wait-%E8%8B%8D%E5%A4%A9%E4%B8%8D%E8%B4%9F%E6%9C%89%E5%BF%83%E4%BA%BA/"/>
</entry>
<entry>
<title>基础博弈</title>
<link href="http://yoursite.com/2019/09/08/%E5%9F%BA%E7%A1%80%E5%8D%9A%E5%BC%88/"/>
<id>http://yoursite.com/2019/09/08/基础博弈/</id>
<published>2019-09-08T12:46:52.000Z</published>
<updated>2019-09-08T13:04:28.037Z</updated>
<content type="html"><![CDATA[<h2 id="基础博弈"><a href="#基础博弈" class="headerlink" title="基础博弈"></a>基础博弈</h2><h4 id="1-博弈论的简介"><a href="#1-博弈论的简介" class="headerlink" title="1. 博弈论的简介"></a><strong>1. 博弈论的简介</strong></h4><a id="more"></a><p> 博弈论是二人或多人在平等的对局中各自利用对方的策略变换自己的对抗策略,达到取胜目标的理论。博弈论是研究互动决策的理论。博弈可以分析自己与对手的利弊关系,从而确立自己在博弈中的优势,因此有不少博弈理论,可以帮助对弈者分析局势,从而采取相应策略,最终达到取胜的目的。博弈的类型分为:合作博弈、非合作博弈、完全信息博弈、非完全信息博弈、静态博弈、动态博弈,等等。</p><h4 id="2-基础概念"><a href="#2-基础概念" class="headerlink" title="2. 基础概念"></a><strong>2. 基础概念</strong></h4><p> 必胜态:通过某一步可以转移到必败态的局面。 也就是说,对于一个处于必胜态的玩家,他总能找到一种合法操作,将当前局面变成一个必败态然后交给对方,如果中途不出现意外的话,最终自己就会得到胜利。但是处于必胜态并不意味着任意的操作都能将当前局面变成必败态。</p><p> 必败态:通过某一步只能转移到必胜态的局面。 也就是说,处于必败态的玩家无论做什么操作,都只会将当前的局面变成必胜态,然后交给对方,只要对方足够聪明,那么该玩家将输掉比赛。</p><p> 对于足够聪明的两个博弈者来说,游戏的胜负在比赛前就已经知道(当然,我这里只是说在题目里,在现实中如果是稍微复杂一点的博弈游戏,单凭人脑是很难达到那种水平),也就是说胜利的一方总能找到胜利的路径,而输掉的那一方无论怎样走,胜利的一方都能找到对应的方法。也就是说先后手以及起始局面可以决定整场博弈的胜负。</p><h4 id="3-巴什博弈(Bash-Game)"><a href="#3-巴什博弈(Bash-Game)" class="headerlink" title="3. 巴什博弈(Bash Game)"></a><strong>3. 巴什博弈(Bash Game)</strong></h4><blockquote><p><strong>只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个。最后取光者得胜。</strong></p></blockquote><p> <u>求 r=n%(1+m), 判断 r 是否等于 0,如果 r 不等于 0,先手必胜,否则后手必胜</u>。为什么?</p><p> 我们可以分析一下,对于 n=(1+m) * r+s,如果 s不等于 0 的话,先手取走s,那么总的物品数剩下 (1+m) * r,然后后手取走 k 的话,先手只要取走 1+m-k 的物品,就可以保持 n=(1+m) 的倍数的局面交给对方,这意味着什么?意味着 n=0 的局面最终会被后手得到,那样后手就输了。而如果s等于0的话,那么对于先手取k的物品,后手只要取 1+m-k 个物品就可以将n=0的局面转给先手,先手就输了。</p><p> 所以这里的必败态是(1+m)的倍数。有没有发现,对于一场博弈来说,所有的必败态都会有相似的地方,就像这里,必败态一定是(1+m)的倍数。</p><p> 然后再说深一点的巴什博弈:只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取p个,最多取q个,如果剩下的物品数小于p的话需要一次取完。最后取光者得胜。</p><p> 这个又怎样求?按照上面的思路,我们可以得到公式n=(p+q)*r+s。</p><p> 那么这里的s有两种情况①s>=p,②s<p,。</p><p> 对于①很容易分析,只要先手取走s的话,对于后手去k,先手只要取p+q-k即可保证先手必胜。</p><p> 对于②,分析起来没有①那么简单,所以这可能就一定需要用后面讲到的用SG值来判断了。</p><p> 然后在讲一下一个问题。如果条件和基本的巴什博弈基本一样,但是说的是最后谁是无法再取物品的是赢家的话,那该怎么处理呢?</p><p> 既然是这样,先手只要判断一下能不能将最后一步留给自己就可以了。而最后一步最少也要保留一个物品,所以我们可以将这个问题转化为基本的巴什博弈,只是终点变成一个物品,而不是零个物品。所以判断的条件是(n-1)%(1+m)!=0 ? 先手赢 : 后手赢。</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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">Bash_Game</span><span class="params">(<span class="keyword">int</span> n,<span class="keyword">int</span> m)</span> </span>{<span class="comment">//是否先手有必赢策略</span></span><br><span class="line"> <span class="keyword">if</span> (n % (<span class="number">1</span> + m) != <span class="number">0</span>) <span class="keyword">return</span> <span class="number">1</span>; <span class="comment">//先手赢 </span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//后手赢</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="例题"><a href="#例题" class="headerlink" title="例题:"></a>例题:</h4><p><strong>1. HDU1846 (模板题)</strong> </p><p><a href="http://acm.hdu.edu.cn/showproblem.php?pid=1846" target="_blank" rel="noopener">http://acm.hdu.edu.cn/showproblem.php?pid=1846</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> t;</span><br><span class="line"> <span class="built_in">cin</span> >> t;</span><br><span class="line"> <span class="keyword">while</span>(t--) {</span><br><span class="line"> <span class="keyword">int</span> n, m;</span><br><span class="line"> <span class="built_in">cin</span> >> n >> m;</span><br><span class="line"> <span class="keyword">int</span> s = n % (<span class="number">1</span> + m);</span><br><span class="line"> <span class="keyword">if</span>(s) <span class="built_in">cout</span> << <span class="string">"first"</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">cout</span> << <span class="string">"second"</span> << <span class="built_in">endl</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></pre></td></tr></table></figure><p><strong>2. HDU4764 (巴什博弈变形)</strong> </p><p><a href="http://acm.hdu.edu.cn/showproblem.php?pid=4764" target="_blank" rel="noopener">http://acm.hdu.edu.cn/showproblem.php?pid=4764</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> n, m;</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">cin</span> >> n >> m && n && m) {</span><br><span class="line"> <span class="keyword">int</span> s = (n - <span class="number">1</span>) % (<span class="number">1</span> + m); <span class="comment">//谁先写到 大于等于n 谁就输</span></span><br><span class="line"> <span class="keyword">if</span>(s) <span class="built_in">cout</span> << <span class="string">"Tang"</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">cout</span> << <span class="string">"Jiang"</span> << <span class="built_in">endl</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></pre></td></tr></table></figure><h4 id="4-尼姆博弈-Nimm-Game-和-扩展"><a href="#4-尼姆博弈-Nimm-Game-和-扩展" class="headerlink" title="4. 尼姆博弈(Nimm Game) 和 扩展"></a>4. 尼姆博弈(Nimm Game) 和 扩展</h4><blockquote><p><strong>有若干堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。</strong></p></blockquote><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">求 r=n%(<span class="number">1</span>+m), 判断 r 是否等于 <span class="number">0</span>,如果 r 不等于 <span class="number">0</span>,先手必胜,否则后手必胜。为什么?</span><br><span class="line"></span><br><span class="line"> 我们可以分析一下,对于 n=(<span class="number">1</span>+m) * r+s,如果 s不等于 <span class="number">0</span> 的话,先手取走s,那么总的物品数剩下 (<span class="number">1</span>+m) * r,然后后手取走 k 的话,先手只要取走 <span class="number">1</span>+m-k 的物品,就可以保持 n=(<span class="number">1</span>+m) 的倍数的局面交给对方,这意味着什么?意味着 n=<span class="number">0</span> 的局面最终会被后手得到,那样后手就输了。而如果s等于<span class="number">0</span>的话,那么对于先手取k的物品,后手只要取 <span class="number">1</span>+m-k 个物品就可以将n=<span class="number">0</span>的局面转给先手,先手就输了。</span><br><span class="line"></span><br><span class="line"> 所以这里的必败态是(<span class="number">1</span>+m)的倍数。有没有发现,对于一场博弈来说,所有的必败态都会有相似的地方,就像这里,必败态一定是(<span class="number">1</span>+m)的倍数。</span><br><span class="line"></span><br><span class="line"> 然后再说深一点的巴什博弈:只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取p个,最多取q个,如果剩下的物品数小于p的话需要一次取完。最后取光者得胜。</span><br><span class="line"></span><br><span class="line"> 这个又怎样求?按照上面的思路,我们可以得到公式n=(p+q)*r+s。</span><br><span class="line"></span><br><span class="line"> 那么这里的s有两种情况①s>=p,②s<p,。</span><br><span class="line"></span><br><span class="line"> 对于①很容易分析,只要先手取走s的话,对于后手去k,先手只要取p+q-k即可保证先手必胜。</span><br><span class="line"></span><br><span class="line"> 对于②,分析起来没有①那么简单,所以这可能就一定需要用后面讲到的用SG值来判断了。</span><br><span class="line"></span><br><span class="line"> 然后在讲一下一个问题。如果条件和基本的巴什博弈基本一样,但是说的是最后谁是无法再取物品的是赢家的话,那该怎么处理呢?</span><br><span class="line"></span><br><span class="line"> 既然是这样,先手只要判断一下能不能将最后一步留给自己就可以了。而最后一步最少也要保留一个物品,所以我们可以将这个问题转化为基本的巴什博弈,只是终点变成一个物品,而不是零个物品。所以判断的条件是(n<span class="number">-1</span>)%(<span class="number">1</span>+m)!=<span class="number">0</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><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="keyword">int</span> <span class="title">Nimm_Game</span><span class="params">(<span class="keyword">int</span> n)</span> </span>{ <span class="comment">//假设n个数存在数组f[]中,有必胜策略返回1</span></span><br><span class="line"> <span class="keyword">int</span> flag = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> flag ^= f[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(flag) <span class="keyword">return</span> <span class="number">1</span>; <span class="comment">//先手赢</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">//后手赢</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="例题-1"><a href="#例题-1" class="headerlink" title="例题:"></a>例题:</h4><p><strong>1. 洛谷 P2197 (尼姆博弈 模板)</strong></p><p><a href="https://www.luogu.org/problem/P2197" target="_blank" rel="noopener">https://www.luogu.org/problem/P2197</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="meta-keyword">include</span> <span class="meta-string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><cstring></span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> t;</span><br><span class="line"> <span class="built_in">cin</span> >> t;</span><br><span class="line"> <span class="keyword">while</span>(t--) {</span><br><span class="line"> <span class="keyword">int</span> n, x, ans = <span class="number">0</span>;;</span><br><span class="line"> <span class="built_in">cin</span> >> n;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> x;</span><br><span class="line"> ans ^= x;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(ans) <span class="built_in">cout</span> << <span class="string">"Yes"</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">else</span> <span class="built_in">cout</span> << <span class="string">"No"</span> << <span class="built_in">endl</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></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><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="comment">// 第一次从b堆中取出a个</span></span><br><span class="line">这个游戏的SG值就是各堆数量的异或和,当 SG 为 <span class="number">0</span> 时先手必败,否则先手就要把SG变为<span class="number">0</span></span><br><span class="line">先检验 SG 值,如果是 <span class="number">0</span> 输出 lose,否则我们按照以下原则行动</span><br><span class="line"></span><br><span class="line">--<span class="comment">//----重点来了------</span></span><br><span class="line">有 n 个数的异或值不为 <span class="number">0</span> 现在要减少一个数使异或值为 <span class="number">0</span></span><br><span class="line"></span><br><span class="line">假设 n 个数:a1 ,a2,a3...an</span><br><span class="line"></span><br><span class="line">a1^a2^a3^..^an=k</span><br><span class="line"></span><br><span class="line">那么我们可以对一个数进行操作,假设这个数是a1,</span><br><span class="line">设 a1^k = a', a'^a2^a3^...^an = a1^a2^a3^...^an^k = k^k = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">所以我们只需要从头到尾检验每个数异或k的值是否比它小(因为是要减少),遇到小的直接输出 ai-ai^k 即可</span><br><span class="line"></span><br><span class="line"><span class="comment">//在这里要明白:</span></span><br><span class="line">假设把每堆石子的数量异或以后得到数为 k (k!=<span class="number">0</span>)</span><br><span class="line"> 这里 k 并不是第一次要取出 k 个石子</span><br><span class="line"> 在这里设用 k 去与每堆f[i]异或得到的一个数为 m</span><br><span class="line"> 若 m < f[i], 则说明第一次是在 第i堆中取了f[i]-k^f[i]个石子</span><br></pre></td></tr></table></figure><h4 id="例题-2"><a href="#例题-2" class="headerlink" title="例题:"></a>例题:</h4><p><strong>1. 洛谷 P1427 (第一次取出)</strong></p><p><a href="https://www.luogu.org/problem/P1247" target="_blank" rel="noopener">https://www.luogu.org/problem/P1247</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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><iostream> </span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"><span class="keyword">int</span> k[<span class="number">500005</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="built_in">cin</span> >> n;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> k[i];</span><br><span class="line"> ans ^= k[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!ans) {</span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"lose"</span> << <span class="built_in">endl</span>;</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"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>((ans ^ k[i]) >= k[i]) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="built_in">cout</span> << k[i] - (ans ^ k[i]) << <span class="string">' '</span><< i << <span class="built_in">endl</span>;</span><br><span class="line"> k[i] ^= ans;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cout</span> << k[i] << <span class="string">' '</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">cout</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>2. HDU 2176 (每次 取出/剩余 )</strong></p><p><a href="http://acm.hdu.edu.cn/showproblem.php?pid=2176" target="_blank" rel="noopener">http://acm.hdu.edu.cn/showproblem.php?pid=2176</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="meta-keyword">include</span> <span class="meta-string"><iostream> </span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span> n;</span><br><span class="line"><span class="keyword">int</span> k[<span class="number">500005</span>];</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">while</span>(<span class="built_in">cin</span> >> n && n) {</span><br><span class="line"> <span class="keyword">int</span> ans = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="built_in">cin</span> >> k[i];</span><br><span class="line"> ans ^= k[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!ans) {</span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"No"</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">cout</span> << <span class="string">"Yes"</span> << <span class="built_in">endl</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">1</span>; i <= n; i++) {</span><br><span class="line"> <span class="keyword">if</span>((ans ^ k[i]) >= k[i]) <span class="keyword">continue</span>;</span><br><span class="line"> <span class="keyword">int</span> t = ans ^ k[i];</span><br><span class="line"> <span class="comment">//t是按照最优的方法取完石子后,剩下的石子</span></span><br><span class="line"> <span class="built_in">cout</span> << k[i] << <span class="string">' '</span><< t << <span class="built_in">endl</span>;</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">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="基础博弈"><a href="#基础博弈" class="headerlink" title="基础博弈"></a>基础博弈</h2><h4 id="1-博弈论的简介"><a href="#1-博弈论的简介" class="headerlink" title="1. 博弈论的简介"></a><strong>1. 博弈论的简介</strong></h4>
</summary>
<category term="Better late than never. 只要开始,虽晚不迟." scheme="http://yoursite.com/tags/Better-late-than-never-%E5%8F%AA%E8%A6%81%E5%BC%80%E5%A7%8B%EF%BC%8C%E8%99%BD%E6%99%9A%E4%B8%8D%E8%BF%9F/"/>
</entry>
<entry>
<title>Linux下使用 Github + Hexo 搭建私人博客</title>
<link href="http://yoursite.com/2019/09/08/Linux%E4%B8%8B%E4%BD%BF%E7%94%A8-Github-Hexo-%E6%90%AD%E5%BB%BA%E7%A7%81%E4%BA%BA%E5%8D%9A%E5%AE%A2/"/>
<id>http://yoursite.com/2019/09/08/Linux下使用-Github-Hexo-搭建私人博客/</id>
<published>2019-09-08T05:46:44.000Z</published>
<updated>2019-09-08T15:49:32.538Z</updated>
<content type="html"><![CDATA[<p><strong>在此声明: 注意输入命令时当前的路径, 没有标注的话就是任意路径</strong></p><a id="more"></a><h3 id="一-搭建Hexo"><a href="#一-搭建Hexo" class="headerlink" title="一. 搭建Hexo"></a>一. 搭建Hexo</h3><h4 id="1-Node-js安装"><a href="#1-Node-js安装" class="headerlink" title="1. Node.js安装"></a>1. Node.js安装</h4><p><strong>首先去官网下载格式为 tar.xz 的安装包 <a href="https://nodejs.org/en/" target="_blank" rel="noopener">官网链接</a>, 然后解压</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/56b8af2997c82c6c.png" alt></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></pre></td><td class="code"><pre><span class="line"><span class="comment">//此操作通过创建软链接执行,语法格式为 ln -s 源文件 目标文件,参数-s为软链接(符号链接)</span></span><br><span class="line">[root@changjianing]<span class="meta"># ln -s /home/changjianing/Downloads/node-v10.16.3-linux-x64/bin/node /usr/local/bin/node</span></span><br><span class="line"></span><br><span class="line">[root@changjianing]<span class="meta"># ln -s /home/changjianing/Downloads/node-v10.16.3-linux-x64/bin/npm /usr/local/bin/npm</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 class="comment">//如果显示: </span></span><br><span class="line"></span><br><span class="line">/usr/local/bin/node已存在 或 /usr/local/bin/npm已存在</span><br><span class="line">就到这个路径(/usr/local/bin/node),把node删了再次执行此命令</span><br><span class="line">或</span><br><span class="line">就到这个路径(/usr/local/bin/npm),把npm删了再次执行此命令</span><br></pre></td></tr></table></figure><h4 id="2-安装-git"><a href="#2-安装-git" class="headerlink" title="2. 安装 git"></a>2. 安装 git</h4><p><code>sudo apt-get install git</code></p><p>给一个学习 git 的网站 <a href="https://www.liaoxuefeng.com/wiki/896043488029600" target="_blank" rel="noopener">Git教程</a></p><h4 id="3-安装-Hexo"><a href="#3-安装-Hexo" class="headerlink" title="3. 安装 Hexo"></a>3. 安装 Hexo</h4><p><strong>Hexo 操作命令官网 <a href="https://hexo.io/docs/commands" target="_blank" rel="noopener">官网链接</a> (了解)</strong></p><p><code>npm install hexo-cli -g //安装Hexo</code></p><p><strong>若此命令不能执行,则进行以下操作 (安装npm)</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="comment">//npm的源在国外,没翻墙的话速度会很慢,可以改成国内的淘宝源 (执行以下3行命令)</span></span><br><span class="line">npm config <span class="built_in">set</span> registry https:<span class="comment">//registry.npm.taobao.org</span></span><br><span class="line">npm config <span class="built_in">list</span></span><br><span class="line">sudo apt-get install npm</span><br><span class="line"></span><br><span class="line"><span class="comment">//然后再安装 Hexo</span></span><br><span class="line">npm install hexo-cli -g (或 npm install -g hexo-cli)</span><br></pre></td></tr></table></figure><p><strong>此处安装完成后,需要将Hexo添加到全局变量中。否则会提示找不到命令</strong></p><p><code>ln -s /home/changjianing/Downloads/node-v10.16.3-linux-x64/lib/node_modules/hexo-cli/bin/hexo /usr/local/bin/hexo</code></p><h4 id="4-部署-Hexo-博客环境"><a href="#4-部署-Hexo-博客环境" class="headerlink" title="4. 部署 Hexo 博客环境"></a>4. 部署 Hexo 博客环境</h4><p><strong>1) 部署 Hexo</strong></p><p><strong>可以放在和 Node.js 同层级的目录</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">[root@changjianing Downloads]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads</span><br><span class="line">[root@changjianing Downloads]<span class="meta"># mkdir hexo</span></span><br><span class="line">[root@changjianing Downloads]<span class="meta"># cd hexo/</span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo init # 新建一个网站,默认在目前的文件夹建立网站。</span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># ll <span class="comment">//ll不行 可以ls</span></span></span><br><span class="line">total <span class="number">168</span></span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">1765</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> _config.yml</span><br><span class="line">drwxr-xr-x <span class="number">285</span> root root <span class="number">12288</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">15</span> node_modules</span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">443</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> package.json</span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">138442</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">15</span> package-lock.json</span><br><span class="line">drwxr-xr-x <span class="number">2</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> scaffolds</span><br><span class="line">drwxr-xr-x <span class="number">3</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> source</span><br><span class="line">drwxr-xr-x <span class="number">3</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> themes</span><br><span class="line">[root@changjianing hexo]<span class="meta"># ll themes/ # 查看自带的主题</span></span><br><span class="line">total <span class="number">4</span></span><br><span class="line">drwxr-xr-x <span class="number">6</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> landscape</span><br></pre></td></tr></table></figure><p><strong>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></pre></td><td class="code"><pre><span class="line">[root@changjianing hexo]<span class="meta"># hexo g # 生成静态文件</span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># ll</span></span><br><span class="line">total <span class="number">200</span></span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">1765</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> _config.yml</span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">25063</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">26</span> db.json</span><br><span class="line">drwxr-xr-x <span class="number">285</span> root root <span class="number">12288</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">15</span> node_modules</span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">447</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">26</span> package.json</span><br><span class="line">-rw-r--r-- <span class="number">1</span> root root <span class="number">138442</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">15</span> package-lock.json</span><br><span class="line">drwxr-xr-x <span class="number">7</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">26</span> <span class="keyword">public</span> # 生成的静态文件</span><br><span class="line">drwxr-xr-x <span class="number">2</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> scaffolds</span><br><span class="line">drwxr-xr-x <span class="number">3</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> source</span><br><span class="line">drwxr-xr-x <span class="number">3</span> root root <span class="number">4096</span> Jun <span class="number">4</span> <span class="number">16</span>:<span class="number">14</span> themes</span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo s # 启动服务,默认是 http:<span class="comment">//localhost:4000</span></span></span><br><span class="line">INFO Start processing</span><br><span class="line">INFO Hexo is running at http:<span class="comment">//localhost:4000 . Press Ctrl+C to stop.</span></span><br></pre></td></tr></table></figure><p><strong>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></pre></td><td class="code"><pre><span class="line">http:<span class="comment">//www.zhangblog.com:4000/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//下面给出别人的访问情况, 自己的没有截图</span></span><br></pre></td></tr></table></figure><p><a href="http://www.zhangblog.com/uploads/hexo/02-hexo-test.png" target="_blank" rel="noopener">访问情况</a></p><h3 id="二-将-Hexo-和-Github-Pages-结合"><a href="#二-将-Hexo-和-Github-Pages-结合" class="headerlink" title="二. 将 Hexo 和 Github Pages 结合"></a>二. 将 Hexo 和 Github Pages 结合</h3><h4 id="1-注册-Github-账号"><a href="#1-注册-Github-账号" class="headerlink" title="1. 注册 Github 账号"></a>1. 注册 Github 账号</h4><p><a href="https://github.com/" target="_blank" rel="noopener">Github 官网</a></p><h4 id="2-使用Github-Pages"><a href="#2-使用Github-Pages" class="headerlink" title="2. 使用Github Pages"></a>2. 使用Github Pages</h4><p><strong>创建指定的Github仓库, 点击创建按钮</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/410105b8626b0a85.png" alt></p><p><strong>仓库名称和配置选择</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/737f51d21bea387f.png" alt></p><p><strong>开启 Github Pages, 进入 Settings</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/663fa4698a59a403.png" alt></p><p><strong>默认已开启 Github Pages</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/ee6b7f5803e60b66.png" alt></p><p><strong>选择主题, 并查看</strong></p><p><a href="https://segmentfault.com/img/bVbwETZ" target="_blank" rel="noopener">具体情况</a></p><p><strong>浏览器访问</strong></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">https:<span class="comment">//zhanglianghhh.github.io/</span></span><br></pre></td></tr></table></figure><p><a href="https://segmentfault.com/img/bVbwET4" target="_blank" rel="noopener">访问情况</a></p><h4 id="3-在Github-上添加-SSH秘钥-并配置"><a href="#3-在Github-上添加-SSH秘钥-并配置" class="headerlink" title="3. 在Github 上添加 SSH秘钥 并配置"></a>3. 在Github 上添加 SSH秘钥 并配置</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><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">[root@changjianing ~]# ssh-keygen -t rsa # 如果遇见等待输入的地方,按下 Enter 回车键即可,无需任何其他输入</span><br><span class="line">Generating public/private rsa key pair.</span><br><span class="line">Enter file in which to save the key (/root/.ssh/id_rsa): </span><br><span class="line">Enter passphrase (empty for no passphrase): </span><br><span class="line">Enter same passphrase again: </span><br><span class="line">Your identification has been saved in /root/.ssh/id_rsa.</span><br><span class="line">Your public key has been saved in /root/.ssh/id_rsa.pub.</span><br><span class="line">The key fingerprint is:</span><br><span class="line">SHA256:73zrQW4LTBgAVqQKvOoTxFrgaGF/sobf643Q+3w7or0 root@zhangblog</span><br><span class="line">The key's randomart image is:</span><br><span class="line">+---[RSA 2048]----+</span><br><span class="line">| o++ |</span><br><span class="line">|oo . . . |</span><br><span class="line">|*oo . . |</span><br><span class="line">|.*o+ . o |</span><br><span class="line">|+oo + S . . |</span><br><span class="line">|oo o. + o |</span><br><span class="line">|. +... + + |</span><br><span class="line">|.. ...*. = o.o |</span><br><span class="line">| .. .*+E+.=o+. |</span><br><span class="line">+----[SHA256]-----+</span><br><span class="line"></span><br><span class="line">[root@changjianing ~]# cd .ssh/</span><br><span class="line"></span><br><span class="line">[root@changjianing .ssh]# ll</span><br><span class="line">total 12</span><br><span class="line">-rw------- 1 root root 0 Jun 3 17:02 authorized_keys</span><br><span class="line">-rw------- 1 root root 1675 Jun 5 14:17 id_rsa</span><br><span class="line">-rw-r--r-- 1 root root 396 Jun 5 14:17 id_rsa.pub</span><br><span class="line">-rw-r--r-- 1 root root 395 Dec 14 17:15 known_hosts</span><br><span class="line">[root@changjianing .ssh]# cat id_rsa.pub # 具体的公钥信息</span><br><span class="line">ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD4iDDDDDDDDDDgMMutdH7KdI5P7BrtHbfRG+MYyr1/Gtz45hJgbVHBCTFZaTn2+MekFQcZVkyc2kEU7L7mm4ZGWkStgbXkas+uTFwo3kLlX8ozcUC3jM8rhzbWPv8piq58ezBnrMZ0zNsCgHGXpokUmLqYt1mpLXz5rsOzwGgHHkp+Wlr+6tTQxr/+9T4CiE/RkFKi/mehn01rjOcVluYSkwkVii03EzMlMcoyV3ctnWzwyZIWAQAsvDSN2CQAdRtaUHOJOAoRv8/s4jDiWU1ia0JYmm2D/IWcLl2hxNtGeVHTFk9l1djtUQu47zuoOM4y6ySlUx28HNIAMw14gjIv5 root@zhangblog</span><br></pre></td></tr></table></figure><p><strong>Github 添加 SSH秘钥</strong></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/763f10177130b2be.png" alt></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/1c5f6361afee5a9f.png" alt></p><p><img src="https://ftp.bmp.ovh/imgs/2019/09/9c78a7c66b050d01.png" alt></p><p><strong>Github 连接测试</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">[root@changjianing ~]<span class="meta"># ssh -T [email protected]</span></span><br><span class="line">The authenticity of host 'github.com (13.250.177.223)' can't be established.</span><br><span class="line">RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.</span><br><span class="line">RSA key fingerprint is MD5:<span class="number">16</span>:<span class="number">27</span>:ac:a5:<span class="number">76</span>:<span class="number">28</span>:<span class="number">2</span>d:<span class="number">36</span>:<span class="number">63</span>:<span class="number">1b</span>:<span class="number">56</span>:<span class="number">4</span>d:eb:df:a6:<span class="number">48.</span></span><br><span class="line">Are you sure you want to continue connecting (yes/no)? yes //输入yes就行</span><br><span class="line">Warning: Permanently added 'github.com,13.250.177.223' (RSA) to the list of known hosts.</span><br><span class="line">Hi zhanglianghhh! You've successfully authenticated, but GitHub does <span class="keyword">not</span> provide shell access.</span><br></pre></td></tr></table></figure><p><strong>可见连接 Github 成功</strong></p><h4 id="4-设置账号信息"><a href="#4-设置账号信息" class="headerlink" title="4. 设置账号信息"></a>4. 设置账号信息</h4><figure class="highlight plain"><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">[root@changjianing hexo]# git config --global user.name "zhanglianghhh" //这里填写你创建网站的名字</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]# git config --global user.email "[email protected]" //这里填写你Github上的邮箱</span><br></pre></td></tr></table></figure><h4 id="5-Hexo-部署到-Github-Pages"><a href="#5-Hexo-部署到-Github-Pages" class="headerlink" title="5. Hexo 部署到 Github Pages"></a>5. Hexo 部署到 Github Pages</h4><p><strong>_config.yml 配置修改</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></pre></td><td class="code"><pre><span class="line">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo <span class="comment">//注意这里的路径(搭建Hexo时创建的hexo文件夹)</span></span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># vim _config.yml</span></span><br><span class="line">………………</span><br><span class="line"># Deployment</span><br><span class="line">## Docs: https:<span class="comment">//hexo.io/docs/deployment.html # 修改或添加如下信息</span></span><br><span class="line">deploy:</span><br><span class="line"> type: git</span><br><span class="line"> repo: [email protected]:zhanglianghhh/zhanglianghhh.github.io.git <span class="comment">//填写自己的信息</span></span><br><span class="line"> branch: master</span><br></pre></td></tr></table></figure><p><strong>在部署到 GitHub 之前,还需要安装如下扩展:</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">[root@changjianing hexo]<span class="meta"># pwd # 站点目录</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># npm install hexo-deployer-git --save</span></span><br></pre></td></tr></table></figure><p><strong>部署到 Github</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">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo d -g # 部署前,先生成静态文件 -g 可选</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></pre></td><td class="code"><pre><span class="line">https:<span class="comment">//zhanglianghhh.github.io/ # GitHub Pages 的访问</span></span><br><span class="line">http:<span class="comment">//www.zhangblog.com/ # 个人网站的访问</span></span><br></pre></td></tr></table></figure><h3 id="三-更换-Hexo主题"><a href="#三-更换-Hexo主题" class="headerlink" title="三. 更换 Hexo主题"></a>三. 更换 Hexo主题</h3><h4 id="1-进入官网挑选喜欢的主题"><a href="#1-进入官网挑选喜欢的主题" class="headerlink" title="1. 进入官网挑选喜欢的主题"></a>1. 进入官网挑选喜欢的主题</h4><p><strong><a href="https://hexo.io/themes/" target="_blank" rel="noopener">Hexo主题官网</a></strong></p><p><strong>可以看到有很多主题给我们选,我们只要选择喜欢的主题点击进去,然后进入到它的github地址,我们只要把这个地址复制下来(例如我是选择:hexo-theme-next这个主题)</strong></p><h4 id="2-克隆主题"><a href="#2-克隆主题" class="headerlink" title="2. 克隆主题"></a>2. 克隆主题</h4><p><strong>再打开 hexo文件夹下的 themes 目录</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">[root@changjianing themes]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo/themes</span><br><span class="line"></span><br><span class="line">[root@changjianing themes]<span class="meta"># git clone https:<span class="comment">//github.com/iissnan/hexo-theme-next(此处地址替换成你需要使用的主题的地址)</span></span></span><br></pre></td></tr></table></figure><p><strong>下载中,等待下载完成</strong></p><h4 id="3-修改hexo配置文件"><a href="#3-修改hexo配置文件" class="headerlink" title="3. 修改hexo配置文件"></a>3. 修改hexo配置文件</h4><p><strong>下载完成后, 打开 hexo 中的 _config.yml 文件</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">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># vim _config.yml</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//修改参数为: theme: hexo-theme-next</span></span><br></pre></td></tr></table></figure><h4 id="4-部署主题-本地查看效果"><a href="#4-部署主题-本地查看效果" class="headerlink" title="4. 部署主题, 本地查看效果"></a>4. 部署主题, 本地查看效果</h4><p><strong>返回 hexo 目录</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">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo g</span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo s</span></span><br></pre></td></tr></table></figure><p><strong>打开浏览器,输入 <code>http://localhost:4000/</code> 即可看见我们的主题已经更换了</strong></p><h4 id="5-如果效果满意-就将它部署到-Github-上"><a href="#5-如果效果满意-就将它部署到-Github-上" class="headerlink" title="5. 如果效果满意, 就将它部署到 Github 上"></a>5. 如果效果满意, 就将它部署到 Github 上</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">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo clean <span class="comment">//必须要,不然有时因为缓存问题,服务器更新不了主题</span></span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo g -d</span></span><br></pre></td></tr></table></figure><h4 id="6-打开自己的主页-即可查看效果"><a href="#6-打开自己的主页-即可查看效果" class="headerlink" title="6. 打开自己的主页, 即可查看效果"></a>6. 打开自己的主页, 即可查看效果</h4><p><strong>更多具体修改请查看对应主题的说明文档</strong></p><h3 id="四-新建-删除-博客文章"><a href="#四-新建-删除-博客文章" class="headerlink" title="四. 新建/删除 博客文章"></a>四. 新建/删除 博客文章</h3><h4 id="1-用-hexo-发表新文章"><a href="#1-用-hexo-发表新文章" class="headerlink" title="1. 用 hexo 发表新文章"></a>1. 用 hexo 发表新文章</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">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo n <span class="meta-string">"文章标题"</span></span></span><br><span class="line"> </span><br><span class="line"><span class="comment">//-----</span></span><br><span class="line">其中 我的家 为文章标题,执行命令 hexo n <span class="string">"我的家"</span> 后</span><br><span class="line">会在项目 \hexo\source_posts 中生成 我的家.md文件,用编辑器打开编写即可</span><br><span class="line"></span><br><span class="line">当然,也可以直接在 \hexo\source\_posts 中新建一个 md 文件,我就是这么做的。 写完后,推送到服务器上,执行以下命令即可在我们的站点看到新的文章。 </span><br><span class="line"></span><br><span class="line"><span class="comment">//如果执行命令: hexo n "文章标题" 出现未找到命令</span></span><br><span class="line"><span class="comment">//则需重装Hexo,执行次命令即可: npm install hexo-cli -g</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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[root@changjianing hexo]<span class="meta"># pwd</span></span><br><span class="line">/home/changjianing/Downloads/hexo</span><br><span class="line"></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo g <span class="comment">//生成</span></span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo d <span class="comment">//部署</span></span></span><br></pre></td></tr></table></figure><p><strong>打开自己的主页,即可查看效果</strong></p><h4 id="2-删除文章"><a href="#2-删除文章" class="headerlink" title="2. 删除文章"></a>2. 删除文章</h4><p><strong>删除文章的过程一样也很简单,先删除本地文件,然后通过生成和部署命令进而将远程仓库中的文件也一并删除。具体来说,以最开始默认形成的 <code>helloworld.md</code> 这篇文章为例。</strong></p><p><strong>首先进入到 <code>/home/changjianing/hexo/source/_post</code> 文件夹中,找到 <code>helloworld.md</code> 文件,在本地直接执行删除</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></pre></td><td class="code"><pre><span class="line">[root@changjianing hexo]<span class="meta"># hexo g <span class="comment">//生成</span></span></span><br><span class="line">[root@changjianing hexo]<span class="meta"># hexo d <span class="comment">//部署</span></span></span><br></pre></td></tr></table></figure><p><strong>然后去主页即可查看效果</strong></p><h3 id="五-参考网址"><a href="#五-参考网址" class="headerlink" title="五. 参考网址"></a>五. 参考网址</h3><p><strong>1. <a href="http://www.zhangblog.com/2019/06/11/hexo01/" target="_blank" rel="noopener">搭建 Hexo</a></strong></p><p><strong>2. <a href="https://segmentfault.com/a/1190000020137776?utm_source=tag-newest" target="_blank" rel="noopener">将 Hexo 和 Github Pages 结合</a></strong></p><p><strong>3. <a href="https://my.oschina.net/ryaneLee/blog/638440" target="_blank" rel="noopener">更换 Hexo 主题 和 新建文章</a></strong></p><p><strong>4. <a href="https://blog.csdn.net/time888/article/details/70249241" target="_blank" rel="noopener">删除文章</a></strong></p>]]></content>
<summary type="html">
<p><strong>在此声明: 注意输入命令时当前的路径, 没有标注的话就是任意路径</strong></p>
</summary>
<category term="Do what you say,say what you do. 做你说过的,说你能做的" scheme="http://yoursite.com/tags/Do-what-you-say-say-what-you-do-%E5%81%9A%E4%BD%A0%E8%AF%B4%E8%BF%87%E7%9A%84%EF%BC%8C%E8%AF%B4%E4%BD%A0%E8%83%BD%E5%81%9A%E7%9A%84/"/>
</entry>
</feed>