Long Luo's Life Notes

每一天都是奇迹

By Long Luo

昨天在B站看到一个数学视频1,比较 \(2^{100!}\)\(2^{100}!\) 的大小。直观感受就是这2个数都非常非常大,但哪个更大无法一眼看出来。

虽然指数爆炸,但阶乘实际上增长的速度比指数更快,如下图1所示:

function graph

可以看出阶乘图像 \(y = x!\) 实际上比指数 \(y = e^x\) 要快很多,而 \(y = x^x\) 是最快的。

但具体哪个更大呢?

这个问题有很多种方法,这里展示了4种方法。

对数放缩法 (Zoom)

由于对数2 函数 \(y = \log_{a}{b}\)\(a > 1\) 是单调递增函数,所以比较两个数大小时,可以通过比较两者对数值来实现大小比较。

两边同取对数 \(\log_{2}{x}\)

左边:

\[ A = \log_{2}{(2^{100!})} = 100! \]

右边:

\[ B = \log_{2}{2^{100}!}= \log_{2}{2^{100}} + \log_{2}{(2^{100} - 1)} + \dots + 1 + 0 \]

共有 \(2^{100}\) 项,值从 \(0\)\(\log_{2}{2^{100}} = 100\) ,所以

\[ B < 100 \cdot 2^{100} < 128 \cdot 2^{100} = 2^7 \cdot 2^{100} = 2^{107} \]

综合上式,我们只需要比较 \(100!\)\(2^{107}\) 的大小即可。

\(100!\) 至少有 \((100 - 64 + 1) = 37\) 项是大于等于 \(64 = 2^6\) ,也就是 \((2^6)^{37}=2^{222}\)

显然可得 \(100! \gg 2^{222} \gg 2^{107}\)

故有虽然两个数都非常大,但 \(2^{100!}\) 仍然远远大于 \(2^{100}!\)

斯特林公式 (Stirling’s Approximation)

由于存在阶乘,我们可以使用斯特林公式(Stirling’s Approximation)3 来估计。

\[ n! \sim \sqrt{2 \pi n}(\frac{n}{e})^n = \sqrt{2 \pi} n^{\frac{n + 1}{2}}e^{-n} \]

两边同取对数:

\[ \ln{n!} \sim \frac{1}{2} ln(2 \pi) + (n+\frac{1}{2}) ln(n) - n \]

根据上式,可见 \(n\) 足够大时,斯特林公式可以近似为:

\[ \ln(n!) \sim n(ln(n) - 1) \]

则有:

\[ \begin{array}{l} A = ln(2^{100!}) = 100! ln(2) \\ B = ln(2^{100}!) \sim 2^{100}(ln(2^{100}) - 1) = 2^{100}(100 ln(2) - 1) \end{array} \]

由于 \(2^{10} = 1024 \approx 10^3\) ,则有 \(2^{100} \approx 10^{30}\) , 那么 \(B \approx 10^{32} ln(2)\)

很明显 \(100! \gg 10^{32}\) ,因此

\[ 2^{100!} \gg 2^{100}! \]

阅读全文 »

By Long Luo

袁哥在微博上发布了一道 数学挑战题

计算 \((3+ \sqrt{5})^n\) 的整数末三位数,给出能口算或者可以用计算器计算的算法的第一个人,免费给一个价值 1000 元的 A9 投资分享群入群名额。 Google_CodeJam_Problem

最开始看到这道题目时,我觉得很简单啊,于是给出了下面的解答:

\(y = (3+ \sqrt{5})^n\) ,两边同取对数,\(\log_{10}{y} = n \log_{10}{(3+\sqrt5)}\)\(y = 10^{n\log_{10}{5.23607}}\)\(lg5 \approx 0.7\) ,所以 \(y \approx 10^{0.7n}\)

但问题没有这么简单,因为上述解答只在 \(n = 1\) 是正确的,\(n = 2\) , \(y = 10^{1.4} = 25\) 就不对了,因为精度不够!

之外,根据评论中其他人给的思路,分析得出这个是周期性的,所以又提交了下面的答案:

Google_CodeJam_log_solution

但问题仍然没有这么简单,因为即使循环周期 \(k = 100\) , \(\log_{10}{(3+\sqrt5)}\) 取的位数再多仍然会出现精度不够的问题。

之后袁哥发布了 解答 ,图片太大,这里放 链接

袁哥的题解省略了很多东西,很多人可能看不太明白。我重新写了题解,重新整理了思路及缺失的步骤,外加证明,有高一数学水平即可看懂。

问题 :

对于任意 \(n \subset N\) , 求 \((3 + \sqrt{5})^n\) 整数部分最后 \(3\) 位。

Solution

\(a^n = (3 + \sqrt{5})^n , b^n = (3 - \sqrt{5})^n\)

\[ f(n) = a^n + b^n \]

证明 1: \(f(x)\) 为整数。 方法〈》: 根据项展开式: \(f(n)=2 \cdot \sum_{k=0}^{n / 2} C_n^{2 k} \cdot 3^{n-2 k} \cdot 5^k\langle(\rangle\)奇次项相消, 证毕!

\[ \begin{aligned} & \text { 方法 }\left\langle 27 \text { 根据 } A^{n+1}+B^{n+1}=(A+B)\left(A^n+B^n\right)-A B\left(A^{n-1}+B^{n-1}\right)\right. \\ & \text { 代入 } A=3+\sqrt{5}, B=3-\sqrt{5}, A B=9-5=4 \\ & \text { 可得: } f_{n+1}=6 f_n-4 f_{n-1}, n \geqslant 1 \quad \ldots . \text { 《2 } \\ & f_0=2, f_1=6, f_2=28, \text { 递推 } f_n C Z^{+} \text {证毕 } \\ & \text { 由 } 0<3-\sqrt{5}<1,0<b^n<1, f_n=N, \end{aligned} \]

\(\Rightarrow N-k a^n<N\) ,故题目转化为求 \(f_n\) 最后 3 位, fn \(\% 1000\) 。根据结果 ans \(=f_n \%\). 1000 , 证明ans是周期性。

证明: \(\because f_n=6 f_n-4 f_{n-1}\), 考虑以下数值对: 模运算法则: \((a * b) \% p=(a \% p * b \% p) \% p\)

\[ a^b \% p=\left((a \% p)^b\right) \% p \]

证明 1: 为整数。 方法〈》: 根据项展开式: 奇次项相消, 证毕!

方法根据代入可得《递推证毕由 ,故题目转化为求 最后 3 位, fn 。根据结果 ans . 1000 , 证明ans是周期性。 证明: , 考虑以下数值对: 模运算法则:

Google_CodeJam_By_Hand_solution_1
Google_CodeJam_By_Hand_solution_2

后来通过搜索,发现这道题是 Google CodeJam1 编程竞赛题,原题如下:

阅读全文 »

By Long Luo

从古到今,人类一直希望机器能够像人一样,代替人们从事各种工作。

机器学习(Machine Learning)是一门引人入胜的领域,通过模拟人脑神经网络,使计算机能够从数据中学习和改进,以完成各种任务。

深度学习(Deep Learning)

神经网络(Neutral Network)

3Blue1Brown深度学习之神经网络的结构 Part 1

在当今数字化的时代,机器学习和神经网络成为了引领人工智能发展的核心技术。其中,手写数字识别作为机器学习领域的一个经典问题,为我们深入探索神经网络的原理提供了绝佳的案例。

这篇文章将首先介绍什么是神经网络,神经网络的实现原理,之后以经典的手写数字识别为例来加强对机器学习的理解。

什么是神经网络?

神经系统的工作方式与身体的其他器官完全不同。在身体的许多器官中,同类型的细胞执行同样的功能,单个细胞的工作就代表整个器官的功能,器官的功能也就是其中每个细胞功能的总和。例如肝脏中的每个肝细胞都执行同样的化学合成和解毒功能,小肠上皮细胞都执行同样的吸收营养的功能,每条肌肉中的肌肉细胞都执行同样的收缩功能等。它们的功能状态受整体器官的控制,细胞之间的信息交换比较少。

与此相反,神经系统以网络的方式进行工作,神经细胞之间有频繁和复杂的信息传递,每个神经细胞的状态都根据其在网络中的位置不同而与其它神经细胞不同,单个神经细胞功能也不能代表整个神经系统的功能

人脑神经网络是由大量的神经元组成,通过突触连接形成复杂的网络。机器学习通过人脑神经网络的启发,构建人工神经网络模型。人工神经网络由节点(神经元)和连接它们的权重组成。权重表示神经元之间的连接强度,信息通过这些连接在网络中传递和处理。

神经网络是如何工作的?

首先,让我们了解一下神经网络的基本结构。神经网络由输入层、隐藏层和输出层组成。输入层接收手写数字的像素值作为输入,隐藏层则负责提取输入特征,输出层给出最终的识别结果。每个神经元都与上一层的所有神经元连接,并带有权重,这些权重决定了每个神经元对信息的贡献程度。

为了训练神经网络,我们需要大量的手写数字样本作为训练数据。训练过程中,神经网络会根据输入数据的真实标签与预测标签之间的误差,通过反向传播算法来更新神经元之间的权重,从而逐渐提高准确性。反向传播算法通过计算每个神经元的梯度,根据梯度的大小来调整权重,使得预测结果与真实标签更加接近。

对于手写数字识别问题,隐藏层的神经元可以学习到不同笔画、曲线等特征,输出层的神经元则对应0到9的数字标签。通过大量的样本和迭代训练,神经网络可以逐渐学习到正确的特征提取和数字分类规则,从而实现准确的手写数字识别。

除了神经网络的结构和训练方法外,还有一些优化技术可以提高手写数字识别的性能。例如,卷积神经网络(Convolutional Neural Networks,CNN)能够有效地利用图像的空间结构特征,提高了识别的准确性和效率。另外,激活函数的选择、正则化技术的应用以及适当的优化算法等都对神经网络的性能起到重要作用。

神经网络是一种受到人脑神经元启发的算法模型,通过多个层次的神经元组成,可以进行复杂的数据处理和模式识别。在手写数字识别中,我们希望机器能够通过训练学习,准确地识别手写的数字。接下来,我们将揭开神经网络的奥秘。

\[ S(x) = {\frac {1}{1 + e^{-x}}} = {\frac {e^{x}}{e^{x} + 1}} = 1 - S(-x) \]

阅读全文 »

By Frank Luo

This is my answers of the MRI Tutorial Videos How MRI Works - Part 2: The Spin Echo and How MRI Works - Part 3:Fourier Transform and K-Space .

Part 2: The Spin Echo

Questions

Part 2 Questions 1
Part 2 Question 2

Answers

Question 1:

  1. The Boltzmann Magetization \(M_0 = \frac{N {\gamma}^2 \hbar^2 B_0}{4 k T}\), then after elimination the units is \(J/T\).
  2. The Polarization is \(P = \frac{\gamma \hbar B_0}{2kT}\), then after elimination we can get that \(P\) is a special number depends on the material, no SI units.

Question 2:

  1. The polarization is \(P = \frac{51-49}{100} = 0.02\) .
  2. The magnet field strength should be \(B_0 = \frac{0.02}{0.0000034} \approx 5882T\) .
  3. The temperature should be \(T = \frac{300 \times 0.0000034}{0.02} = 0.051K\).

Question 3:

  1. Since the Boltzmann Magetization Equation is \(M = M_0(1- e^{-\frac{t}{T_1}}) e^{-\frac{t}{T_2}}\) , so we can calculate the signal.

The signal of Tissue \(A\) : \(M_A = M_0(1- e^{-\frac{150}{300}}) e^{-\frac{12.5}{20}} = 0.21\) . The signal of Tissue \(B\) : \(M_B = M_0(1- e^{-\frac{150}{200}}) e^{-\frac{12.5}{40}} = 0.38\) .

Surely Tissue \(B\) will deliver more signal.

  1. We have calculated that Tissue \(B\) will deliver more signal if both Tissue \(A\) and \(B\) has the same Boltzmann Magetization.

If Tissue \(A\) is \(85\%\) of Tissue \(B\), then the Tissue \(A\) signal will become lesser, so Tissue \(B\) deliver more signal.

  1. Let function \(f(t) = M_{0A}(1- e^{-\frac{TR}{T_{1A}}})e^{-\frac{t}{T_{2A}}} - M_{0B}(1- e^{-\frac{TR}{T_{1B}}})e^{-\frac{t}{T_{2B}}}\) reprent the signal of time \(t\).

Consider the function: \(f(t) = (1 - e^{-\frac{150}{200}}) e^{-\frac{t}{40}} - (1- e^{-\frac{150}{300}}) e^{-\frac{t}{20}}\) reaches its PEAK at about \(t = 16\), so the \(TE\) should be \(TE = 32ms\).

阅读全文 »

By Long Luo

Startup

1
2
3
4
5
% gdb -help         	print startup help, show switches
*% gdb object normal debug
*% gdb object core core debug (must specify core file)
%% gdb object pid attach to running process
% gdb use file command to load object

Help

1
2
3
4
5
6
7
*(gdb) help        	list command classes
(gdb) help running list commands in one command class
(gdb) help run bottom-level help for a command "run"
(gdb) help info list info commands (running program state)
(gdb) help info line help for a particular info command
(gdb) help show list show commands (gdb state)
(gdb) help show commands specific help for a show comma

Breakpoints

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*(gdb) break main       set a breakpoint on a function
*(gdb) break 101 set a breakpoint on a line number
*(gdb) break basic.c:101 set breakpoint at file and line (or function)
*(gdb) info breakpoints show breakpoints
*(gdb) delete 1 delete a breakpoint by number
(gdb) delete delete all breakpoints (prompted)
(gdb) clear delete breakpoints at current line
(gdb) clear function delete breakpoints at function
(gdb) clear line delete breakpoints at line
(gdb) disable 2 turn a breakpoint off, but don't remove it
(gdb) enable 2 turn disabled breakpoint back on
(gdb) tbreak function|line set a temporary breakpoint
(gdb) commands break-no ... end set gdb commands with breakpoint
(gdb) ignore break-no count ignore bpt N-1 times before activation
(gdb) condition break-no expression break only if condition is true
(gdb) condition 2 i == 20 example: break on breakpoint 2 if i equals 20
(gdb) watch expression set software watchpoint on variable
(gdb) info watchpoints show current watchpoints

Running the program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
*(gdb) run        	run the program with current arguments
*(gdb) run args redirection run with args and redirection
(gdb) set args args... set arguments for run
(gdb) show args show current arguments to run
*(gdb) cont continue the program
*(gdb) step single step the program; step into functions
(gdb) step count singlestep \fIcount\fR times
*(gdb) next step but step over functions
(gdb) next count next \fIcount\fR times
*(gdb) CTRL-C actually SIGINT, stop execution of current program
*(gdb) attach process-id attach to running program
*(gdb) detach detach from running program
*(gdb) finish finish current function's execution
(gdb) kill kill current executing program

Stack backtrace

1
2
3
4
5
6
*(gdb) bt        	print stack backtrace
(gdb) frame show current execution position
(gdb) up move up stack trace (towards main)
(gdb) down move down stack trace (away from main)
*(gdb) info locals print automatic variables in frame
(gdb) info args print function parameters

Browsing source

1
2
3
4
5
6
7
8
9
10
11
12
13
*(gdb) list 101        	list 10 lines around line 101
*(gdb) list 1,10 list lines 1 to 10
*(gdb) list main list lines around function
*(gdb) list basic.c:main list from another file basic.c
*(gdb) list - list previous 10 lines
(gdb) list *0x22e4 list source at address
(gdb) cd dir change current directory to \fIdir\fR
(gdb) pwd print working directory
(gdb) search regexpr forward current for regular expression
(gdb) reverse-search regexpr backward search for regular expression
(gdb) dir dirname add directory to source path
(gdb) dir reset source path to nothing
(gdb) show directories show source path

Browsing Data

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
*(gdb) print expression        print expression, added to value history
*(gdb) print/x expressionR print in hex
(gdb) print array[i]@count artificial array - print array range
(gdb) print $ print last value
(gdb) print *$->next print thru list
(gdb) print $1 print value 1 from value history
(gdb) print ::gx force scope to be global
(gdb) print 'basic.c'::gx global scope in named file (>=4.6)
(gdb) print/x &main print address of function
(gdb) x/countFormatSize address low-level examine command
(gdb) x/x &gx print gx in hex
(gdb) x/4wx &main print 4 longs at start of \fImain\fR in hex
(gdb) x/gf &gd1 print double
(gdb) help x show formats for x
*(gdb) info locals print local automatics only
(gdb) info functions regexp print function names
(gdb) info variables regexp print global variable names
*(gdb) ptype name print type definition
(gdb) whatis expression print type of expression
*(gdb) set variable = expression assign value
(gdb) display expression display expression result at stop
(gdb) undisplay delete displays
(gdb) info display show displays
(gdb) show values print value history (>= gdb 4.0)
(gdb) info history print value history (gdb 3.5)

Object File manipulation

1
2
3
4
5
(gdb) file object      		load new file for debug (sym+exec)
(gdb) file discard sym+exec file info
(gdb) symbol-file object load only symbol table
(gdb) exec-file object specify object to run (not sym-file)
(gdb) core-file core post-mortem debugging

Signal Control

1
2
3
4
5
6
7
8
9
10
(gdb) info signals        	print signal setup
(gdb) handle signo actions set debugger actions for signal
(gdb) handle INT print print message when signal occurs
(gdb) handle INT noprint don't print message
(gdb) handle INT stop stop program when signal occurs
(gdb) handle INT nostop don't stop program
(gdb) handle INT pass allow program to receive signal
(gdb) handle INT nopass debugger catches signal; program doesn't
(gdb) signal signo continue and send signal to program
(gdb) signal 0 continue and send no signal to program

Machine-level Debug

1
2
3
4
5
6
7
8
9
10
11
12
13
(gdb) info registers        	print registers sans floats
(gdb) info all-registers print all registers
(gdb) print/x $pc print one register
(gdb) stepi single step at machine level
(gdb) si single step at machine level
(gdb) nexti single step (over functions) at machine level
(gdb) ni single step (over functions) at machine level
(gdb) display/i $pc print current instruction in display
(gdb) x/x &gx print variable gx in hex
(gdb) info line 22 print addresses for object code for line 22
(gdb) info line *0x2c4e print line number of object code at address
(gdb) x/10i main disassemble first 10 instructions in \fImain\fR
(gdb) disassemble addr dissassemble code for function around addr

History Display

1
2
3
4
5
6
7
8
9
(gdb) show commands        	print command history (>= gdb 4.0)
(gdb) info editing print command history (gdb 3.5)
(gdb) ESC-CTRL-J switch to vi edit mode from emacs edit mode
(gdb) set history expansion on turn on c-shell like history
(gdb) break class::member set breakpoint on class member. may get menu
(gdb) list class::member list member in class
(gdb) ptype class print class members
(gdb) print *this print contents of this pointer
(gdb) rbreak regexpr useful for breakpoint on overloaded member name

Miscellaneous

1
2
3
4
5
(gdb) define command ... end        define user command
*(gdb) RETURN repeat last command
*(gdb) shell command args execute shell command
*(gdb) source file load gdb commands from file
*(gdb) quit quit gdb

Also see this: pdf

参考文献

GDB Cheat Sheet https://bytes.usc.edu/cs104/wiki/gdb/

Gdb Cheat Sheet https://web.stanford.edu/~ouster/cs111-spring23/gdb/

GDB的那些奇淫技巧 https://evilpan.com/2020/09/13/gdb-tips/

0%