Archive for November, 2008

SICP习题解答:第一章(下)

?View Code SCHEME
;; 1.29
(define (simpson-integral f a b n)
  (define (coefficient i)
    (cond ((or (= i 0) (= i n)) 1)
          ((even? i) 2)
          (else 4)))
  (let ((h (/ (- b a)n )))
    (* (/ h 3)
       (sum (lambda (i) (* (f (+ a (* i h))) (coefficient i)))
            0
            (lambda (i) (+ i 1))
            n))))
 
;; 1.30
(define (sum term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (+ result (term a)))))
  (iter a 0))
 
;; 1.31 只需要把sum改动两处。
; 递归实现
(define (product term a next b)
  (if (> a b)
      1
      (* (term a)
         (product term (next a) next b))))
 
; 迭代实现
(define (product term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (* result (term a)))))
  (iter a 1))
 
; 阶乘
(define (factorial n)
  (product (lambda (x) x) 1 (lambda (i) (+ 1 i)) n))
 
; π的近似值
(define (calc-pi n)
  (define (term i)
    (/ (- (square i) 1) (square i)))
  (define (next i)
    (+ 2 i))
  (* 4 (product term 3.0 next n)))
 
;; 1.32
(define (accumulate combiner null-value term a next b)
  (if (> a b)
      null-value
      (combiner (term a)
                (accumulate combiner null-value term (next a) next b))))
 
(define (accumulate combiner null-value term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (combiner result (term a)))))
  (iter a null-value))
 
;; 1.33
; filtered-accumulate 的两种实现
(define (filtered-accumulate combiner null-value term a next b filter)
  (define (do-filter x)
    (if (filter x) x null-value))
  (if (> a b)
      null-value
      (combiner (do-filter (term a))
                (filtered-accumulate combiner null-value term (next a) next b filter))))
 
(define (filtered-accumulate combiner null-value term a next b filter)
  (define (do-filter x)
    (if (filter x) x null-value))
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (combiner result (do-filter (term a))))))
  (iter a null-value))
 
; (a)
(filtered-accumulate + 0 (lambda (x) x) a (lambda (i) (+ 1 i)) b prime?)
; (b)
(filtered-accumulate * 1 (lambda (x) x) 1 (lambda (i) (+ 1 i)) (- 1 n) (lambda (a) (= 1 (gcd a n))))
 
;; 1.34 (f f)相当于(f 2),相当于(2 2),会因为2并非可以调用的函数而出错。
 
;; 1.35 证明不动点直接计算即可,计算的(fixed-point (lambda (x) (+ 1 (/ 1 x))) 1.0)。
 
;; 1.36 全部代码如下
(define tolerance 0.00001)
 
(define (fixed-point f first-guess)
  (define (close-enough? v1 v2)
    (< (abs (- v1 v2)) tolerance))
  (define (try guess)
    (display guess)
    (newline)
    (let ((next (f guess)))
      (if (close-enough? guess next)
          next
          (try next))))
  (try first-guess))
 
(define (f x) (/ (log 1000) (log x)))
 
(display (fixed-point f 2))
(newline) (newline)
(display (fixed-point (lambda (x) (average x (f x))) 2))
(newline) (newline)
 
; 使用与不使用平均阻尼的步数分别为9与34步。
 
;; 1.37
; 递归版本
(define (cont-frac n d k)
  (define (shift f)
    (lambda (i) (f (+ 1 i))))
  (if (= 0 k)
      0
      (/ (n 1) (+ (d 1) (cont-frac (shift n) (shift d) (- k 1))))))
 
; 迭代版本
(dsefine (cont-frac n d k)
  (define (iter result i)
    (if (= 0 i)
        result
        (iter (/ (n i) (+ (d i) result)) (- i 1))))
  (iter 0 k))
 
; 当k不小于11时,结果有4位精度。
 
;; 1.38
(define (e-2 k)
  (cont-frac (lambda (i) 1.0)
             (lambda (i)
               (if (= 2 (remainder i 3))
                   (* 2 (/ (+ 1 i) 3))
                   1))
             k))
 
;; 1.39
(define (tan-cf x k)
  (cont-frac (lambda (i)
               (if (= 1 i) x (- (square x))))
             (lambda (i)
               (- (* 2 i) 1))
             k))
 
;; 1.40
(define (cubic a b c)
  (lambda (x)
    (+ c (* x (+ b (* x (+ a x)))))))
 
;; 1.41
; double函数
(define (double f)
  (lambda (x)
    (f (f x))))
 
;; (((double (double double)) inc) 5) 的值为21。因为 (double double) 得到一个把参数过程应用四次的函数,而 (double (double double)) 事实上是将“把参数过程应用四次”的过程应用两次,也就是一个将参数过程应用十六次的函数。
 
;; 1.42
(define (compose f g)
  (lambda (x) (f (g x))))
 
;; 1.43
(define (repeated f n)
  (if (= 1 n)
      f
      (compose f (repeated f (- n 1)))))
 
;; 1.44
(define (n-times-smooth f dx n)
  ((repeated (lambda (f) (smooth f dx)) n) f))
 
;; 1.45
(define (calc-nth-root-with-t-average-damps x n t)
  (fixed-point ((repeated average-damp t) (lambda (y) (/ x (fast-expt y (- n 1))))) 1.0))
 
;; 通过实验,得到的规律是,当 2^t>=n 时,用 t 次平均阻尼求 n 次方根是可行的,于是有下面的程序。
(define (nth-root x n)
  (define (minimal-t n)
    (if (= 1 n)
        0
        (+ 1 (minimal-t (quotient n 2)))))
  (calc-nth-root-with-t-average-damps x n (minimal-t n)))
 
;; 1.46
(define (iterative-improve guess improve good-enough?)
  (if (good-enough? guess)
      guess
      (iterative-improve (improve guess) improve good-enough?)))
 
(define (sqrt x)
  (define (improve y)
    (/ (+ x (square y)) (* 2 y)))
  (define (good-enough? y)
    (> tolerance (abs (- (square y) x))))
  (iterative-improve 1.0 improve good-enough?))
 
(define (fixed-point f first-guess)
  (define (improve x)
    (f x))
  (define (good-enough? x)
    (> tolerance (abs (- (f x) x))))
  (iterative-improve first-guess improve good-enough?))

Comments (2)

SICP习题解答:第一章(上)

?View Code SCHEME
;; 1.1-2 略
 
;; 1.3
(define (greater-two a b c)
  (-
   (+ a b c)
   (min a b c)))
; 或
(define (greater-two a b c)
  (cond ((and (> b a) (> c a))
         (+ b c))
        ((and (> a b) (> c b))
         (+ a c))
        (else (+ a b))))
 
;; 1.4 (if (> b 0) + -) 根据b的正负性返回函数+或-。
 
;; 1.5 函数p的定义 (define (p) (p)) 是不断递归调用自己,所以欲对其进行求值/展开会产生死循环。调用 (test 0 (p)) 时,若采用应用序求值,会先对函数的参数,包括 (p) 求值,因而产生死循环,无法输出结果;若采用正则序求值,则由于 (p) 的值事实上不会被展开,故会正常返回0。
 
;; 1.6 将在调用函数 new-if 时,应用序要求先算出其所有参数的值,new-if 的后两个参数——代表 if 的两个分支的代码都将被执行。所以 (sqrt-iter guess x) 必然需要调用 (sqrt-iter (improve guess x) x),这导致死循环。
 
;; 1.7
(define (sqrt x)
  (define (sqrt-iter guess)
    (define (good-enough?)
      (< (abs (/ (- (* guess guess) x) x)) 0.001))
    (define (improve)
      (define (average a b)
        (/ (+ a b) 2))
      (average guess (/ x guess)))
    (if (good-enough?)
        guess
        (sqrt-iter (improve))))
  (sqrt-iter 1.0))
 
;; 1.8
(define (cube-root x)
  (define (iter guess)
    (define (good-enough?)
      (< (abs (/ (- (* (* guess guess) guess) x) x)) 0.001))
    (define (improve)
      (/ (+ ( / x (* guess guess)) (* 2 guess)) 3))
    (if (good-enough?)
        guess
        (iter (improve))))
  (iter 1.0))
 
;; 1.9 第一个过程是递归的,表达式被递归地逐渐展开再合并;第二个过程中的递归是尾递归,不妨理解为迭代的。
 
;; 1.10 (f n)是n的2倍,(g n)是2的n次方,(h n)是2的(h (- n 1))次方。
 
;; 1.11
; 递归方式
(define (f n)
  (if (< n 3) n
      (+ (f (- n 1))
         (* 2 (f (- n 2)))
         (* 3 (f (- n 3))))))
 
; 迭代方式
 
(define (f n)
  (define (iter a b c i)
    (if (= i n) c
        (iter b c
              (+ (* 3 a) (* 2 b) c)
              (+ i 1))))
  (if (< n 3) n
      (iter 0 1 2 2)))
 
;; 1.12
(define (C n i)
  (if (or (= i 0) (= i n))
      1
      (+ (C (- n 1) (- i 1)) (C (- n 1) i))))
 
;; 1.13 可利用归纳法和定义直接证。
 
;; 1.14 空间复杂度为 O(amount),因为任何时刻调用链的长度(栈上的函数数量)不超过 amount+1;时间复杂度为 O(amount * result),因为每得到一种方案都调用一次 (cc 0 kinds-of-coins)。
 
;; 1.15 空间与时间复杂度均为O(log a)。
 
;; 1.16 prod*a^m是不变量。
(define (fast-expt b n)
  (define (iter prod a m)
    (if (= 0 m) prod
        (if (= 0 (remainder m 2))
            (iter prod (* a a) (/ m 2))
            (iter (* prod a) (* a a) (/ (- m 1) 2)))))
  (iter 1 b n))
 
;; 1.17
(define (fast-multi a b)
  (if (= 1 a) b
      (if (= 0 (remainder a 2))
          (double (fast-multi (halve a) b))
          (+ b (double (fast-multi (halve (- a 1)) b))))))
 
;; 1.18
(define (fast-multi a b)
  (define (iter sum i n)
    (if (= 0 n) sum
        (if (= 0 (remainder n 2))
            (iter sum (double i) (halve n))
            (iter (+ sum i) (double i) (halve (- n 1))))))
  (iter 0 a b))
 
;; 1.19 p’ = pp + qq,q’ = qq + 2pq。
 
;; 1.20 应用序需要4次;正则序需要更多,没仔细数,因为gcd函数体中出现了三处b,当b是调用remainder的形式时,它需要被展开若干次。
 
;; 1.21 略。
 
;; 1.22-24 我用的DrScheme没有定义runtime……555
 
;; 1.25 如果不在计算乘幂时随时取模,每次乘法将由于被乘数位数的迅速增长而不能被看做单位时间的原子操作。
 
;; 1.26 每次(expmod base exp m)当exp为正偶数时会调用两次而非一次(expmod base exp m),f(N)=2*f(N/2)+Θ(1)导致f(N)=Θ(N),而原始版本的f(N)=f(N/2)+Θ(1)导致f(N)=Θ(log N)。
 
;; 1.27 以下程序中,(find-carmichael n)找出不超过n的Carmichael数
 
(define (prime? n)
  (define (iter i)
    (cond
      ((> (square i) n) true)
      ((= 0 (remainder n i)) false)
      (else (iter (+ i 1)))))
  (iter 2))
 
(define (carmichael? n)
  (define (iter i)
    (cond
      ((= i n) true)
      ((not (= i (expmod i n n))) false)
      (else (iter (+ i 1)))))
  (and (not (prime? n)) (iter 2)))
 
(define (find-carmichael n)
  (define (iter i)
    (cond ((carmichael? i) (display i) (display "\n")))
    (cond ((< i n) (iter (+ i 1)))))
  (iter 2))
 
;; 1.28
(define (miller-rabin n)
  (define (exp-iter prod base exp)
    (cond ((and (< 1 prod) (< prod (- n 1)) (= (remainder (* prod prod) n) 1)) 0)
          ((= 0 exp) prod)
          (else (if (even? exp)
                    (exp-iter
                     prod
                     (remainder (* base base) n)
                     (/ exp 2))
                    (exp-iter
                     (remainder (* prod base) n)
                     (remainder (* base base) n)
                     (/ (- exp 1) 2))))))
  (define (check i)
    (= 1 (exp-iter 1 i (- n 1))))
  (define (check-iter i)
    (cond ((= i 0) true)
          (else (if (check (+ 2 (random (- n 3))))
                    (check-iter (- i 1)) false))))
  (or (= 2 n) (= 3 n)
      (and (< 2 n) (= 1 (remainder n 2)) (check-iter 20))))

Comments (5)

2008年11月24日

昨天,ACM/ICPC杭州赛区以金奖(第五名)谢幕。对于Genesis队,本赛季的所有比赛已经结束,以后不大可能再在比赛中看到我们这支队伍了,希望Genesis得到的两块regional金牌以及一直以来的表现能让关注我们的人满意。

对于我已经研一的两名队友,这大约是他们最后一次以队员的身份出现在ACM/ICPC的赛场上;与高远(xgy)、杨克特(T_T)两位学长的无间配合是太过愉快的经历,学长的经验也让我受益良多。

而对于我,一名正式进入大学才三个月的大一新生,一切才刚刚开始;前方还长的路让人激动憧憬,请相信我会带来更多惊喜。

其实,这赛季能够连拿两金,取得对于我这种新手来说可称辉煌的成绩,不仅取决于全队的努力,对于我自己来说,其实不乏运气成分。这学期我主要的突破是仔细读了本《简明数论》(其实这书只有一半名副其实,“明晰”是无疑的,“简单”则谈不上),打下了还算扎实的数论基础,差不多能应付Regional中通常的数论题了,结果我们队参加的哈尔滨和杭州两个赛区正好都有数论题出现,特别是我们在哈尔滨最后才解出的B题更是我们夺金的关键。另外,在杭州赛的前几天,我匆匆浏览了《柔性字符串匹配》的后半部分,主要内容是用有限自动机做正则表达式匹配。对那本书的主题我自然是一知半解,不过倒对有限自动机有了较多的感受和认识。没想到杭州赛区的H题就是判断两个有限确定性自动机是否等价的题目。虽然没见过,但正好这几天见识了很多与自动机有关的内容,灵光一现就得出了算法,使我们队解出了第6题,也是场上解出的最后一道关键题目。

这样看来,我第一年的ACM/ICPC征程真可称顺风顺水,似乎幸运眷顾,完全没遇到挫折地走下来。当然,以后还是老老实实提高自身实力才是王道,近期打算学学Java,读读SICP之类的书。

这个学期还剩下大约一半,除了为了保持状态做点SRM以外,就不再寻求编程竞赛方面的突破了,应该多尝试点不同的内容。学Java达到与目前的C++近似的熟练程度,读SICP、Concrete Maths、Programming Pearls是必须完成的内容,如果还有闲暇就打算读读Algorithm Design以及一些AI方面的书目。最近一本《数学分析原理》让我多少发现了纯数学的美感,虽然这学期应该不大可能了,但以后还是要读些纯数学的经典教材的。物理是这学期多少令人头疼的科目,得抓紧看一下,希望能培养出兴趣。

好吧,读书去了。

Comments (8)

《数学分析原理》旁注(上)

注:凡“旁注”性质的笔记,都是无规划不成系统的读书随想。尤其与我大多数短篇的读书笔记一样,并不求别人也看懂。

第1章 (2008.11.16)

1.24:引入复数的一切都很完美,只是这个乘法的定义还是略显突兀。能否通过M1~M5以及零元、幺元等内容将这个定义更顺畅地推导或引入呢?换句话说,有了很自然的加法的定义,要满足(1,0)为幺元以及M1~M5,有了这些条件能否得出“合理”的乘法定义有哪些?于是就是函数方程了。如果这是唯一满足的定义那就完美了,不过我的推测是:它是函数方程所有解中明显、特殊、或朴素的一个。

1.35:又是那种“神来之笔”的证明……怎样理解这优美的构造?

1.A.9:任何两个具有最小上界性的有序域同构。我会找到它的证明。

第2章 (2008.11.17)

这章的目的为何?完全不明白,也没办法搞清定理之间的联系。

2.12:可数个可数集的并是可数集。

2.23:所以同为开集与闭集的集就仅有空集和全集。

2.23:紧集,对于集合的每个开覆盖,存在一个有限子集也是开覆盖。

2.44:Cantor集的概念。

第3章 (2008.11.17)

这章的目的应该是判断及求得数列以及级数的极限。

3.1:极限的概念可以直接在度量空间中定义。

3.21:定理能按数列与级数两种语言来叙述与应用。

3.27:正项不增序列a_i的级数收敛当且仅当2^k a_{2^k}的级数收敛。这可以用相对很稀疏的项判断级数的收敛性。

3.38:幂级数的收敛圆(由根值法推出)。

3.42:∑a_n有界,b_n单调递减到0,∑a_n b_n收敛。(分部法)推论:交错递减则收敛。

3.47:级数乘积的定义有卷积的味道。

3.53:对(收敛但非绝对收敛的)级数重排会改变收敛的值!奇妙……

数列:单调有界定理,比较法,Cauchy准则。

级数:比较法,3.27,另一种形式叙述的Cauchy准则,比率法与根值法(3.37说明前者有效的后者一定有效),收敛半径,分部法及推论。

第4章 (2008.11.18)

4.8:函数 f: X->Y 连续,当且仅当对于Y的每个开集V,f-1(V)是是X中的开集。(由于开集的补集是闭集,所以叙述中可以换成闭集。)

4.18:一致连续是函数(在某个定义域上)的性质,而连续是函数在点上的性质。然而在紧集上,这两个概念等价。

4.23:函数的连续性保持定义域的连通性。

这章应该是探讨了函数的连续性与第2章中集合的特性的关系。2、4两章应该都是构建后文微分、积分理论大厦的基石与原材料。

第5章 (2008.11.19)

5.9:直接证一般中值定理,很赞。

5.12:导函数可以不连续,但不能有第一类间断,且在区间内能像连续函数一样取到所有中间值。

5.13:L’Hospital法则的证明,看上去很不直观。Wikipedia上的证明似乎更优美。

5.15:这个证Taylor定理/Lagrange余项的方法简洁得很诡异,其实没看懂……Wikipedia上的先证integral reminder再用积分中值定理直接得到Lagrange reminder的方法直接且精炼。

第6章 (2008.11.20-21)

6.1:这个定义与Wikipedia上的Darboux integral完全相同。上积分、下积分——它们必定存在,可积性便等价于二者是否相等——于我是新鲜的概念。以下便用这些定义(还有一个“加细”)证明了若干关于可积性的性质。

6.2:在概念中增添“-Stieltjes”之后,让关于x的Riemann积分可以关于任意函数α(x),扩充的要点是,α不必可导,甚至不必连续。

6.15:有点绕……第一遍没看明白。不过的确是一下子让人发现Riemann-Stieltjes对于Riemann的扩充,然后函数值、级数(6.16)都可用一个Riemann-Stieltjes积分来表示,6.18是点出本质的总结。

6.20-21:微积分基本定理的两部分。我总是觉得Wikipedia上的证明一下子就能看懂,这书故作高深的倾向却要让人看很久才知道他是怎么证出来的……这种从定义就开始“立意求高”类似于“伤人乎不?问马。”,教材中的例子有萧树铁的《大学数学——代数与几何》中对行列式的定义。这样的教材的确有境界,不过最好还是借助大众化的Wikipedia补充一下。

Comments (2)

《简明数论》的简明笔记(中):13~21节

  • Euler函数φ(m),定义,积性不完全;
    • \phi(m)=m\prod_{p|m}(1-\frac{1}{p})
    • \phi(m)=m\sum_{d|m}\frac{\mu(d)}{d}
    • \sum_{d|m}\phi(d)=m
      • 用积性证很简单;证明二:按与m的最大公约数分类。
  • f(n)的Mobius变换:F(n)=\sum_{d|n}f(d)
    • Mobius逆变换:f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d})
      • 以上两式等价,f(n)与F(n)的积性也等价。
    • f与g的Dirichlet卷积:h(n)=\sum_{d|n}f(d)g(\frac{n}{d}),h保持f与g的积性。
  • 同余:
    • a对模m的最小非负剩余、绝对最小剩余;
    • 同余式是等价关系;同余式可加减乘;ca≡cb (mod m)等价于a≡b (mod m/(c,m) );
    • 对模m的逆的定义。
  • 同余类、完全剩余系定义;
    • 既约剩余系包含的同余类个数即φ(m)。
    • (a,m)=1时,x遍历m的完全/既约剩余系当且仅当ax遍历m的完全/既约剩余系。
      • 用这个可轻松证明Fermat-Euler定理。
  • Wilson定理,即(p-1)! ≡ -1 (mod p)。
    • 证:除了-1外,其它因子可与(不相等的)逆元配对抵消。
    • 即,p的既约剩余系的积模p得-1。
      • 扩展:p可换成pk,2pk(这两者p是奇素数)。
    • 事实上,r不取1,2,4,pk,2pk时,r的既约剩余系的积模r得1。
  • ax≡b (mod m) 型的同余方程。
    • (a,m)|b 是有解的充要条件,解有(a,m)个。
      • 可求a对m的所有逆元。
    • 注意到一个解是 x_0 = a^{\phi(m)-1}b,也可用扩展欧几里德求特解。
    • 所有解是x_0 + \frac{m}{(a,m)}t,其中0<=t<(a,m)。
  • 形如x \equiv a_i \pmod{m_i}的一次同余方程组。
    • 若{m_i}两两既约,则解数必为1(中国剩余定理)。
      • 解为x \equiv \sum M_i M_i^{-1}a_i \pmod{m}
      • 其中m = \prod m_i = M_i m_iM_i M_i^{-1} \equiv 1 \pmod{m_i}
      • 当a_i分别遍历m_i的完全/既约剩余系时,x遍历m的完全/既约剩余系。
    • 若{m_i}并非两两既约,例如(m_i,m_j)=a时,可将模m_i与m_j的两个方程化成模a、m_i/a、m_j/a的三个方程。
      • 编程时,直接化为若干个模p^k的方程似更简便,其中p^k || [m_1,m_2,...,m_i,...]。
    • f(x)≡0 (mod n) 的解数设为 T(f;n),则T(f;n)是关于n的积性函数。
      • 于是只需研究f(x)≡0 (mod p^k)型方程的解法。
      • 即求解多个方程后再解个模{p^k}的一次同余方程组。

Leave a Comment