最大子段和

我们都知道最大子段和可以这样写:

int sum = 0, ans = 0;
for(int i = 1; i <= n; i++) {
	ans = max(ans, sum = max(0, sum + a[i])); 
}

那么,最大子段和为什么是正确的呢?
小编也非常好奇,那么我们就来证明一下吧!

我们先用 Bird Meertens Formalism 写下一个证明:

M S S = ↑ / ⋅ + / ∗ ⋅ s e g s = ↑ / ⋅ + / ∗ ⋅ + + / ⋅ t a i l s ∗ ⋅ i n i t s = ↑ / ⋅ ( ↑ / ⋅ + / ∗ ⋅ t a i l s ) ∗ ⋅ i n i t s     < ⊕ / ⋅ + + / = ⊕ / ⋅ ( ⊕ / ) ∗ > = ↑ ⋅ ⊙ ↛ 0 ∗ i n i t s     < a ⊙ b = ( a + b ) ↑ 0 > = ↑ ⋅ ⊙ → 0 MSS\\=\uparrow/\cdot +/*\cdot segs\\=\uparrow/\cdot +/*\cdot ++/\cdot tails*\cdot inits\\=\uparrow/\cdot(\uparrow/\cdot +/*\cdot tails)*\cdot inits \ \ \ <\oplus/\cdot++/=\oplus/\cdot(\oplus/)*>\\=\uparrow \cdot \odot\nrightarrow_0*inits\ \ \ <a \odot b=(a+b)\uparrow 0>\\=\uparrow \cdot \odot\rightarrow_0 MSS=/+/segs=/+/++/tailsinits=/(/+/tails)inits   </++/=/(/)>=0inits   <ab=(a+b)0>=0

但这里就有严谨的小朋友要问了, 这个证明真的是对的吗?
那么,让我们用 agda 证明吧!
(这份 15KB 的代码刷新了小编的代码长度记录)

module mss where

import Relation.Binary.PropositionalEquality as Eq
open Eq using (__; __; refl; trans; sym; cong; cong-app; subst)
open Eq.-Reasoning using (begin_; _≡⟨⟩_; step-; _)

open import Function using (id; __)

open import Data.Integer
open import Data.Integer.Properties

data ℤ∞ : Set where
  fin : ℤ → ℤ∞
  -: ℤ∞

_+'_ : ℤ∞ → ℤ∞ → ℤ∞ 
fin a +' fin b = fin (a + b) 
fin a +' -= --+' -= --+' fin a = -_⊔'_ : ℤ∞ → ℤ∞ → ℤ∞ 
fin a ⊔' fin b = fin (ab)
fin a ⊔' -= fin a
-∞ ⊔' -= --∞ ⊔' fin a = fin a 


module semigroup where
  record IsSemigroup {A : Set} (__ : AAA) : Set where
    field assoc :x y z(xy)zx(yz)

  open IsSemigroup public-add-is-semigroup : IsSemigroup _+_-add-is-semigroup .assoc = +-assoc--is-semigroup : IsSemigroup __--is-semigroup .assoc =-assoc

  open import Data.List using (List; _++_; [])
  open import Data.List.Properties using (++-assoc)
  List-++-is-semigroup :{A : Set}IsSemigroup {List A} _++_
  List-++-is-semigroup .assoc = ++-assoc

open semigroup


ℤ∞-add-is-semigroup : IsSemigroup _+'_
ℤ∞-add-is-semigroup .assoc (fin x) (fin y) (fin z) rewrite-add-is-semigroup .assoc x y z = refl
ℤ∞-add-is-semigroup .assoc (fin x) (fin y) -= refl
ℤ∞-add-is-semigroup .assoc (fin x) -(fin z) = refl
ℤ∞-add-is-semigroup .assoc (fin x) --= refl
ℤ∞-add-is-semigroup .assoc -(fin x) (fin z) = refl
ℤ∞-add-is-semigroup .assoc -(fin y) -= refl
ℤ∞-add-is-semigroup .assoc --(fin z) = refl
ℤ∞-add-is-semigroup .assoc ---= refl

ℤ∞--is-semigroup : IsSemigroup _⊔'_
ℤ∞--is-semigroup .assoc (fin x) (fin y) (fin z) rewrite--is-semigroup .assoc x y z = refl
ℤ∞--is-semigroup .assoc (fin x) (fin y) -= refl
ℤ∞--is-semigroup .assoc (fin x) -(fin z) = refl
ℤ∞--is-semigroup .assoc (fin x) --= refl
ℤ∞--is-semigroup .assoc -(fin y) (fin z) = refl
ℤ∞--is-semigroup .assoc --(fin z) = refl
ℤ∞--is-semigroup .assoc -(fin y) -= refl
ℤ∞--is-semigroup .assoc ---= refl


module monoid where
  record IsMonoid {A : Set} (e : A) (__ : AAA) : Set where
    field
      is-semigroup : IsSemigroup __
      identityˡ :xexx
      identityʳ :xxex

  open IsMonoid public-add-is-monoid : IsMonoid +0 _+_-add-is-monoid .is-semigroup =-add-is-semigroup-add-is-monoid .identityˡ = +-identityˡ
  ℤ-add-is-monoid .identityʳ = +-identityʳ

  open import Data.List using (List; _++_; [])
  open import Data.List.Properties using (++-identityˡ; ++-identityʳ)
  List-++-is-monoid :{A : Set}IsMonoid {List A} [] _++_
  List-++-is-monoid .is-semigroup = List-++-is-semigroup
  List-++-is-monoid .identityˡ = ++-identityˡ
  List-++-is-monoid .identityʳ = ++-identityʳ

open monoid

ℤ∞-add-is-monoid : IsMonoid (fin +0) _+'_ 
ℤ∞-add-is-monoid .is-semigroup = ℤ∞-add-is-semigroup 
ℤ∞-add-is-monoid .identityˡ (fin x) rewrite-add-is-monoid .identityˡ x = refl
ℤ∞-add-is-monoid .identityˡ -= refl 
ℤ∞-add-is-monoid .identityʳ (fin x) rewrite-add-is-monoid .identityʳ x = refl
ℤ∞-add-is-monoid .identityʳ -= refl

ℤ∞--is-monoid : IsMonoid -_⊔'_ 
ℤ∞--is-monoid .is-semigroup = ℤ∞--is-semigroup 
ℤ∞--is-monoid .identityˡ (fin x) = refl
ℤ∞--is-monoid .identityˡ -= refl 
ℤ∞--is-monoid .identityʳ (fin x) = refl
ℤ∞--is-monoid .identityʳ -= refl-+-distrib :(z x y :)((xy) + z)((x + z)(y + z))-+-distrib z x y = mono--distrib-(+-monoˡ-z) x y 

distrib :(z x y : ℤ∞)((x ⊔' y) +' z)((x +' z) ⊔' (y +' z))
distrib (fin z) (fin x) (fin y) rewrite-+-distrib z x y = refl
distrib (fin z) (fin x) -= refl
distrib (fin z) -(fin x) = refl
distrib (fin z) --= refl
distrib -(fin x) (fin y) = refl
distrib -(fin x) -= refl
distrib --(fin x) = refl
distrib ---= refl

module MSS (
    extensionality :{A : Set} {B : ASet}
        {f g : (x : A)B x}((x : A)f xg x)
        ---------------------fg
  ) where

  open import Data.Nat using (; _+_; zero; suc; __)
  open import Data.List using (List; []; __; [_]; _++_; foldl; foldr; map; scanl; scanr)

  

  reduce :{A : Set}(AAA)AList AA
  reduce __ e [] = e
  reduce __ e (xxs) = __ x (reduce __ e xs)   
  
  map-rule :{A : Set} {B : Set} (f : AB) (xs : List A) (ys : List A)map f (xs ++ ys)(map f xs) ++ (map f ys) 
  map-rule f [] ys = refl
  map-rule f (xxs) ys = 
    begin f xmap f (xs ++ ys) 
      ≡⟨ cong (__ (f x)) (map-rule f xs ys)f xmap f xs ++ map f ysmap-o-rule :{A : Set} {B : Set} {C : Set} (f : AB) (g : BC) (xs : List A)(map gmap f) xsmap (gf) xs 
  map-o-rule f g [] = refl
  map-o-rule f g (xxs) rewrite map-o-rule f g xs = refl

  map-f-rule' :{A : Set} {B : Set} {f : AB} {g : AB}fg(xs : List A)map f xsmap g xs 
  map-f-rule' {f} {g} lam [] = refl
  map-f-rule' {f} {g} lam (xxs) rewrite map-f-rule' lam xs | cong-app lam x = refl

  map-f-rule :{A : Set} {B : Set} {f : AB} {g : AB}fgmap fmap g
  map-f-rule {f} {g} lam = extensionality (map-f-rule' lam)

  inits :{A : Set}List AList (List A)
  inits = scanl _++_ []map [_]

  tails :{A : Set}List AList (List A)
  tails [] = [][] 
  tails (xxs) = (xxs)tails xs 

  concat :{A : Set}List (List A)List A
  concat = foldr _++_ []

  segs :{A : Set}List AList (List A)
  segs = concatmap tailsinits

  sum : List ℤ∞ → ℤ∞ 
  sum = reduce _+'_ (fin +0)

  maximum : List ℤ∞ → ℤ∞
  maximum = reduce _⊔'_ (-)

  mss : List ℤ∞ → ℤ∞
  mss = maximummap sumsegs

  mss-fast : List ℤ∞ → ℤ∞
  mss-fast xs = maximum (scanl (λ a b(a +' b) ⊔' (fin +0)) (fin +0) xs)
  
  -- Did you know there are plenty of useful theorems in the standard library?
  open import Data.Nat.Properties using (+-distribˡ-; +-distribʳ-)
  -- +-distribˡ-⊔ : ∀ x y z → x + (y ⊔ z) ≡ (x + y) ⊔ (x + z)
  -- +-distribʳ-⊔ : ∀ z x y → (x ⊔ y) + z ≡ (x + z) ⊔ (y + z)

  reduce-lam :{A : Set} (__ : AAA) (e : A) (xs : List A) (ys : List A)IsMonoid e __reduce __ e (xs ++ ys)(reduce __ e xs)(reduce __ e ys)
  reduce-lam __ e [] ys lam = 
    begin reduce __ e ([] ++ ys)  
      ≡⟨ reflreduce __ e ys 
      ≡⟨ sym  (identityˡ lam (reduce __ e ys))e(reduce __ e ys)
      ≡⟨ refl(reduce __ e [])(reduce __ e ys)reduce-lam __ e (xxs) ys lam = 
    begin x(reduce __ e (xs ++ ys)) 
      ≡⟨ cong (__ x) (reduce-lam __ e xs ys lam)x((reduce __ e xs)(reduce __ e ys))
      ≡⟨ sym (assoc (is-semigroup lam) x (reduce __ e xs) (reduce __ e ys))((x(reduce __ e xs))reduce __ e ys)join-f-rule :{A : Set} {B : Set} (__ : BBB) (e : B) (f : AB) (xs : List (List A))IsMonoid e (__)((reduce __ e)map fconcat) xs(reduce __ e) (map ((reduce __ e)(map f)) xs)
  join-f-rule __ e f [] lam = refl
  join-f-rule __ e f (xxs) lam = 
    begin (reduce __ emap fconcat) (xxs) 
      ≡⟨ refl(reduce __ e) (map f (x ++ concat xs))
      ≡⟨ cong (reduce __ e) (map-rule f x (concat xs))(reduce __ e) (map f x ++ (map f (concat xs)))
      ≡⟨ reduce-lam __ e (map f x) (map f (concat xs)) lam(reduce __ e (map f x))(reduce __ e (map f (concat xs)))
      ≡⟨ cong (__ (reduce __ e (map f x))) (join-f-rule __ e f xs lam)((reduce __ emap f) xreduce __ e (map (reduce __ emap f) xs))-- going from the back is convinient 
  folder-rule :{A : Set} (__ : AAA) (ep : A) (__ : AAA) 
    (et : A) (xs : List A) (p : A) (q : A)IsMonoid ep __IsMonoid et __((z x y : A)(xy)z(xz)(yz))(reduce __ et (pxs))foldl (λ a b(ab)et) q xsfoldl (λ a b(ab)et) (pq) xs 
  folder-rule __ ep __ et [] p q l1 l2 l3 rewrite identityʳ l2 p = refl
  folder-rule __ ep __ et (xxs) p q l1 l2 l3 = 
    begin (reduce __ et (pxxs)foldl (λ a b(ab)et) q (xxs))
      ≡⟨ refl(reduce __ et (pxxs)foldl (λ a b(ab)et) ((qx)et) xs)
      ≡⟨ refl(p(xreduce __ et xs))foldl (λ a b(ab)et) ((qx)et) xs  
      ≡⟨ sym (cong (_(foldl (λ a b(ab)et) ((qx)et) xs)) (assoc (is-semigroup l2) p x (reduce __ et xs)))((px)reduce __ et xs)foldl (λ a b(ab)et) ((qx)et) xs  
      ≡⟨ reflreduce __ et ((px)xs)foldl (λ a b(ab)et) ((qx)et) xs  
      ≡⟨ folder-rule __ ep __ et xs (px) ((qx)et) l1 l2 l3foldl (λ a b(ab)et) ((px)((qx)et)) xs  
      ≡⟨ sym (cong-app (cong (foldl (λ a b(ab)et)) (assoc (is-semigroup l1) (px) (qx) et)) xs)foldl (λ a b(ab)et) (((px)(qx))et) xs  
      ≡⟨ sym (cong-app (cong (foldl (λ a b(ab)et)) (cong (_et) (l3 x p q))) xs)foldl (λ a b(ab)et) (((pq)x)et) xs  
      ≡⟨ reflfoldl (λ a b(ab)et) (pq) (xxs)hornor-rule :{A : Set} (__ : AAA) (ep : A) (__ : AAA) (et : A)IsMonoid ep __IsMonoid et __((z x y : A)(xy)z(xz)(yz)) -- distri(xs : List A)((reduce __ ep)map (reduce __ et)tails) xsfoldl (λ a b(ab)et) et xs

  hornor-rule __ ep __ et l1 l2 l3 [] = 
    (reduce __ epmap (reduce __ et)) (tails [])
      ≡⟨ refl(reduce __ epmap (reduce __ et)) ([][])   
      ≡⟨ identityʳ l1 etethornor-rule __ ep __ et l1 l2 l3 (xxs) = 
    begin (reduce __ epmap (reduce __ et)tails) (xxs) 
      ≡⟨ refl(reduce __ epmap (reduce __ et))  ((xxs)tails xs)
      ≡⟨ refl(reduce __ ep) ((reduce __ et (xxs))map (reduce __ et) (tails xs))
      ≡⟨ refl(reduce __ et (xxs))((reduce __ ep) (map (reduce __ et) (tails xs)))
      ≡⟨ cong (__ (reduce __ et (xxs))) ( hornor-rule __ ep __ et l1 l2 l3 xs)(reduce __ et (xxs))(foldl (λ a b(ab)et) et xs)
      ≡⟨ folder-rule __ ep __ et xs x et l1 l2 l3foldl (λ a b(ab)et) (xet) xs 
      ≡⟨ sym(cong-app (cong (foldl (λ a b(ab)et)) (cong (_et) (identityˡ l2 x))) xs)foldl (λ a b(ab)et) et (xxs)hornor-rule-f :{A : Set} (__ : AAA) (ep : A) (__ : AAA) (et : A)IsMonoid ep __IsMonoid et __((z x y : A)(xy)z(xz)(yz)) -- distri((reduce __ ep)map (reduce __ et)tails)foldl (λ a b(ab)et) et
  hornor-rule-f  __ ep __ et l1 l2 l3 = extensionality (hornor-rule __ ep __ et l1 l2 l3)
  
  fold-scan-rule :{A : Set} (f : AAA) (e : A) (p : A) (ps : List A) (xs : List A)map (foldl f e) (scanl _++_ (pps) (map [_] xs))map (foldl f (f e p)) (scanl _++_ ps (map [_] xs)) 
  fold-scan-rule f e p ps [] = refl
  fold-scan-rule f e p ps (xxs) rewrite fold-scan-rule f e p (ps ++ (x[])) xs =  refl 
  
  scan-rule :{A : Set} (f : AAA) (e : A) (xs : List A)(map (foldl f e)) (inits xs)scanl f e xs
  scan-rule f e [] = refl
  scan-rule f e (xxs) = 
    begin emap (foldl f e) (scanl _++_ [ x ] (map [_] xs)) 
      ≡⟨ cong (__ e) (fold-scan-rule f e x [] xs)emap (foldl f (f e x)) (scanl _++_ [] (map [_] xs)) 
      ≡⟨ cong (__ e) (scan-rule f (f e x) xs)escanl f (f e x) xsprof :(xs : List ℤ∞)mss xsmss-fast xs 
  prof xs = 
    begin mss xs 
      ≡⟨ refl(maximummap sumconcatmap tailsinits) xs
    -- (max / ∘ + / * ∘ ++ / ) = max / ∘ (max / ∘ + / *) *  
      ≡⟨ join-f-rule _⊔'_ -sum ((map tailsinits) xs) ℤ∞--is-monoid(maximummap (maximummap sum)map tailsinits) xs
      ≡⟨ cong maximum (map-o-rule tails (maximummap sum) (inits xs))(maximummap (maximummap sumtails)inits) xs
      ≡⟨ cong-app (cong (__ maximum) (map-f-rule (hornor-rule-f _⊔'_ -_+'_ (fin +0) ℤ∞--is-monoid  ℤ∞-add-is-monoid distrib))) (inits xs)-- ep = (fin +0) ? 
    (maximummap (foldl (λ a b(a +' b) ⊔' (fin +0)) (fin +0))inits) xs
      ≡⟨ cong maximum (scan-rule (λ a b(a +' b) ⊔' (fin +0)) (fin +0) xs)maximum (scanl (λ a b(a +' b) ⊔' (fin +0)) (fin +0) xs)
      ≡⟨ reflmss-fast xsderivation : mssmss-fast
  derivation = extensionality prof

  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值