SF习题答案(3)(LF-Lists)

介绍

Coq是一个定理证明辅助助手,在对一些关键系统进行形式化证明时十分重要的证明工具。本博客是针对《Software Foundation》的第一卷《LOGICAL FOUNDATIONS》中的习题进行解答,在阅读的过程中请参考书籍进行阅读。

Lists

Exercise 1: 1 star, standard (snd_fst_is_swap)

Theorem snd_fst_is_swap : ∀(p : natprod),
(snd p, fst p) = swap_pair p.
Proof.
(* FILL IN HERE *) Admitted.

解析:参考示例中定理“surjective_pairing”的证明,使用策略“destruct”即可完成证明。

Theorem snd_fst_is_swap : forall (p : natprod),
  (snd p, fst p) = swap_pair p.
Proof.
  intros p. destruct p as [n m]. simpl. reflexivity. Qed

Exercise 2: 1 star, standard, optional (fst_swap_is_snd)

Theorem fst_swap_is_snd : ∀(p : natprod),
fst (swap_pair p) = snd p.
Proof.

解析:同上一题。。

Theorem fst_swap_is_snd : forall (p : natprod),
  fst (swap_pair p) = snd p.
Proof.
  intros p. destruct p as [n m]. simpl. reflexivity. Qed.

Exercise 3: 2 stars, standard, recommended (list_funs)

Complete the definitions of nonzeros, oddmembers, and countoddmembers below. Have a look at the tests to understand what these functions should do.
Fixpoint nonzeros (l:natlist) : natlist
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_nonzeros:
nonzeros [0;1;0;2;3;0;0] = [1;2;3].
(
FILL IN HERE ) Admitted.
Fixpoint oddmembers (l:natlist) : natlist
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_oddmembers:
oddmembers [0;1;0;2;3;0;0] = [1;3].
(
FILL IN HERE ) Admitted.
Definition countoddmembers (l:natlist) : nat
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_countoddmembers1:
countoddmembers [1;0;3;1;4;5] = 4.
(
FILL IN HERE ) Admitted.
Example test_countoddmembers2:
countoddmembers [0;2;4] = 0.
(
FILL IN HERE ) Admitted.
Example test_countoddmembers3:
countoddmembers nil = 0.
(
FILL IN HERE *) Admitted.

解析:根据测试举例的不同,可知各个函数的意义。其中“nonzeros”是求得原列表的非零列表;“oddmembers”是求得原列表中数为奇数的列表;“countoddmembers”是计算列表中奇数的个数。根据这些意义,写出相应的函数定义。

Fixpoint nonzeros (l:natlist) : natlist :=
  match l with
  | nil => nil
  | h :: t => match h with
              | O => nonzeros t
              | nat => h :: nonzeros t
              end
  end.

Example test_nonzeros: nonzeros [0;1;0;2;3;0;0] = [1;2;3].
Proof. reflexivity. Qed.

Fixpoint oddmembers (l:natlist) : natlist :=
  match l with
  | nil => nil
  | h :: t => match h with
              | O => oddmembers(t)
              | nat => match evenb(nat) with
                       | true => oddmembers t
                       | false => h :: oddmembers(t)
                       end
              end
  end.

Example test_oddmembers: oddmembers [0;1;0;2;3;0;0] = [1;3].
Proof. reflexivity. Qed.

Fixpoint countoddmembers (l:natlist) : nat :=
  match l with
  | nil => O
  | h :: t => match h with
              | O => countoddmembers(t)
              | nat => match evenb(nat) with
                       | true => countoddmembers(t)
                       | false => S (countoddmembers t)
                       end
              end
  end.

Example test_countoddmembers1: countoddmembers [1;0;3;1;4;5] = 4.
Proof. reflexivity. Qed.
Example test_countoddmembers2: countoddmembers [0;2;4] = 0.
Proof. reflexivity. Qed.
Example test_countoddmembers3: countoddmembers nil = 0.
Proof. reflexivity. Qed.

Exercise 4: 3 stars, advanced (alternate)

Complete the definition of alternate, which interleaves two lists into one, alternating between elements taken from the first list and elements from the second. See the tests below for more specific examples.
(Note: one natural and elegant way of writing alternate will fail to satisfy Coq’s requirement that all Fixpoint definitions be “obviously terminating.” If you find yourself in this rut, look for a slightly more verbose solution that considers elements of both lists at the same time. One possible solution involves defining a new kind of pairs, but this is not the only way.)
Fixpoint alternate (l1 l2 : natlist) : natlist
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_alternate1:
alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].
(
FILL IN HERE ) Admitted.
Example test_alternate2:
alternate [1] [4;5;6] = [1;4;5;6].
(
FILL IN HERE ) Admitted.
Example test_alternate3:
alternate [1;2;3] [4] = [1;4;2;3].
(
FILL IN HERE ) Admitted.
Example test_alternate4:
alternate [] [20;30] = [20;30].
(
FILL IN HERE *) Admitted.

解析:从测试的举例中可知函数“alternate”是将两个列表交错合并起来,根据这个意义,写出相关函数定义。

Fixpoint alternate (l1 l2 : natlist) : natlist :=
  match l1 with
  | nil => l2
  | h1 :: t1 => match l2 with
                | nil => h1 :: t1
                | h2 :: t2 => [ h1 ; h2 ] ++ (alternate t1 t2)
                end
  end.

Example test_alternate1: alternate [1;2;3] [4;5;6] = [1;4;2;5;3;6].
Proof. reflexivity. Qed.
Example test_alternate2: alternate [1] [4;5;6] = [1;4;5;6].
Proof. reflexivity. Qed.
Example test_alternate3: alternate [1;2;3] [4] = [1;4;2;3].
Proof. reflexivity. Qed.
Example test_alternate4: alternate [] [20;30] = [20;30].
Proof. reflexivity. Qed.

Exercise 5: 3 stars, standard, recommended (bag_functions)
Complete the following definitions for the functions count, sum, add, and member for bags.
Fixpoint count (v:nat) (s:bag) : nat
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
All these proofs can be done just by reflexivity.
Example test_count1: count 1 [1;2;3;1;4;1] = 3.
(
FILL IN HERE ) Admitted.
Example test_count2: count 6 [1;2;3;1;4;1] = 0.
(
FILL IN HERE ) Admitted.
Multiset sum is similar to set union: sum a b contains all the elements of a and of b. (Mathematicians usually define union on multisets a little bit differently — using max instead of sum — which is why we don’t use that name for this operation.) For sum we’re giving you a header that does not give explicit names to the arguments. Moreover, it uses the keyword Definition instead of Fixpoint, so even if you had names for the arguments, you wouldn’t be able to process them recursively. The point of stating the question this way is to encourage you to think about whether sum can be implemented in another way — perhaps by using functions that have already been defined.
Definition sum : bag → bag → bag
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_sum1: count 1 (sum [1;2;3] [1;4;1]) = 3.
(
FILL IN HERE ) Admitted.
Definition add (v:nat) (s:bag) : bag
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_add1: count 1 (add 1 [1;4;1]) = 3.
(
FILL IN HERE ) Admitted.
Example test_add2: count 5 (add 1 [1;4;1]) = 0.
(
FILL IN HERE ) Admitted.
Definition member (v:nat) (s:bag) : bool
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_member1: member 1 [1;4;1] = true.
(
FILL IN HERE ) Admitted.
Example test_member2: member 2 [1;4;1] = false.
(
FILL IN HERE *) Admitted.

解析:从测试示例中知道函数”count”是求列表中中某一个数值的个数,根据这个意义写出”count”的递归定义即可。参数类型bag下的sum也就是将函数app的参数类型进行拓展即可。函数” member”是判断集合中是否有第一个参数值,有为true,没有为false,可以直接利用函数” count”。计算出值大于1就是说明集合中有这个值还不止一个,所以为”true”,否则为”false”。

Fixpoint count (v:nat) (s:bag) : nat :=
  match s with
  | nil => O
  | h :: t => match v =? h with
              | true => S (count v t)
              | false => count v t
              end
  end.

Example test_count1:              count 1 [1;2;3;1;4;1] = 3.
Proof. reflexivity. Qed.
Example test_count2:              count 6 [1;2;3;1;4;1] = 0.
Proof. reflexivity. Qed.

Definition sum : bag -> bag -> bag := app.

Example test_sum1:              count 1 (sum [1;2;3] [1;4;1]) = 3.
Proof. reflexivity. Qed.

Definition add (v:nat) (s:bag) : bag :=
  cons v s.

Example test_add1:                count 1 (add 1 [1;4;1]) = 3.
Proof. reflexivity. Qed.
Example test_add2:                count 5 (add 1 [1;4;1]) = 0.
Proof. reflexivity. Qed.

Definition member (v:nat) (s:bag) : bool :=
  1 <=? (count v s).

Example test_member1:             member 1 [1;4;1] = true.
Proof. reflexivity. Qed.
Example test_member2:             member 2 [1;4;1] = false.
Proof. reflexivity. Qed.

Exercise 6: 3 stars, standard, optional (bag_more_functions)

Here are some more bag functions for you to practice with. When remove_one is applied to a bag without the number to remove, it should return the same bag unchanged. (This exercise is optional, but students following the advanced track will need to fill in the definition of remove_one for a later exercise.)
Fixpoint remove_one (v:nat) (s:bag) : bag
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_remove_one1:
count 5 (remove_one 5 [2;1;5;4;1]) = 0.
(
FILL IN HERE ) Admitted.
Example test_remove_one2:
count 5 (remove_one 5 [2;1;4;1]) = 0.
(
FILL IN HERE ) Admitted.
Example test_remove_one3:
count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.
(
FILL IN HERE ) Admitted.
Example test_remove_one4:
count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.
(
FILL IN HERE ) Admitted.
Fixpoint remove_all (v:nat) (s:bag) : bag
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_remove_all1: count 5 (remove_all 5 [2;1;5;4;1]) = 0.
(
FILL IN HERE ) Admitted.
Example test_remove_all2: count 5 (remove_all 5 [2;1;4;1]) = 0.
(
FILL IN HERE ) Admitted.
Example test_remove_all3: count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.
(
FILL IN HERE ) Admitted.
Example test_remove_all4: count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.
(
FILL IN HERE ) Admitted.
Fixpoint subset (s1:bag) (s2:bag) : bool
(
REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_subset1: subset [1;2] [2;1;4;1] = true.
(
FILL IN HERE ) Admitted.
Example test_subset2: subset [1;2;2] [2;1;4;1] = false.
(
FILL IN HERE *) Admitted.

解析:从测试的示例中知道函数” remove_one”是为了将第二个参数集合中的第一个参数值第一次出现时移除,函数” remove_all”是移除所有的相等的值,使用递归的方式定义即可,不断判断当下值是否为参数值,遍历一遍即可。函数” subset”是判断第一个参数集合是不是第二个参数集合的子集,对第一个参数集合中的每一个元素使用函数”count”计算,只要每个元素第一个集合的个数都小于第二个集合的个数即为”true”,否则为”false”。

Fixpoint remove_one (v:nat) (s:bag) : bag :=
  match s with
  | nil => nil
  | h :: t => match h =? v with
              | true => t
              | false => cons h (remove_one v t)
              end
  end.

Example test_remove_one1: count 5 (remove_one 5 [2;1;5;4;1]) = 0.
Proof. reflexivity. Qed.
Example test_remove_one2: count 5 (remove_one 5 [2;1;4;1]) = 0.
Proof. reflexivity. Qed.
Example test_remove_one3: count 4 (remove_one 5 [2;1;4;5;1;4]) = 2.
Proof. reflexivity. Qed.
Example test_remove_one4: count 5 (remove_one 5 [2;1;5;4;5;1;4]) = 1.
Proof. reflexivity. Qed.

Fixpoint remove_all (v:nat) (s:bag) : bag :=
  match s with
  | nil => nil
  | h :: t => match h =? v with
              | true => remove_all v t
              | false => cons h (remove_all v t)
              end
  end.

Example test_remove_all1:  count 5 (remove_all 5 [2;1;5;4;1]) = 0.
Proof. reflexivity. Qed.
Example test_remove_all2:  count 5 (remove_all 5 [2;1;4;1]) = 0.
Proof. reflexivity. Qed.
Example test_remove_all3:  count 4 (remove_all 5 [2;1;4;5;1;4]) = 2.
Proof. reflexivity. Qed.
Example test_remove_all4:  count 5 (remove_all 5 [2;1;5;4;5;1;4;5;1;4]) = 0.
Proof. reflexivity. Qed.

Fixpoint subset (s1:bag) (s2:bag) : bool :=
  match s1 with
  | nil => true
  | h :: t => match (count h s1) <=? (count h s2) with
              | true => subset t s2
              | false => false
              end
  end.

Example test_subset1:              subset [1;2] [2;1;4;1] = true.
Proof. reflexivity. Qed.
Example test_subset2:              subset [1;2;2] [2;1;4;1] = false.
Proof. reflexivity. Qed.

Exercise 7: 3 stars, standard (list_exercises)

More practice with lists:
Theorem app_nil_r : ∀l : natlist,
l ++ [] = l.
Proof.
(* FILL IN HERE ) Admitted.
Theorem rev_app_distr: ∀l1 l2 : natlist,
rev (l1 ++ l2) = rev l2 ++ rev l1.
Proof.
(
FILL IN HERE ) Admitted.
Theorem rev_involutive : ∀l : natlist,
rev (rev l) = l.
Proof.
(
FILL IN HERE ) Admitted.
There is a short solution to the next one. If you find yourself getting tangled up, step back and try to look for a simpler way.
Theorem app_assoc4 : ∀l1 l2 l3 l4 : natlist,
l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.
Proof.
(
FILL IN HERE ) Admitted.
An exercise about your implementation of nonzeros:
Lemma nonzeros_app : ∀l1 l2 : natlist,
nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).
Proof.
(
FILL IN HERE *) Admitted.

解析:使用归纳、重写等策略,一步一步完成即可。

Theorem app_nil_r : forall l : natlist,
  l ++ [] = l.
Proof.
  intros l. induction l as [| n l'].
  - simpl. reflexivity.
  - simpl. rewrite -> IHl'. reflexivity. Qed.

Theorem rev_app_distr: forall l1 l2 : natlist,
  rev (l1 ++ l2) = rev l2 ++ rev l1.
Proof.
  intros l1 l2. induction l1 as [| a l1'].
  - simpl. rewrite -> app_nil_r. reflexivity.
  - simpl. rewrite -> IHl1'. rewrite -> app_assoc. reflexivity. Qed.

Theorem rev_nat_r : forall n : nat, forall l : natlist,
  rev (l ++ [n]) = n :: rev (l).
Proof.
  intros n l. induction l as [| a l'].
  - simpl. reflexivity.
  - simpl. rewrite -> IHl'. reflexivity. Qed.

Theorem rev_involutive : forall l : natlist,
  rev (rev l) = l.
Proof.
  intros l. induction l as [| n l'].
  - reflexivity.
  - simpl. rewrite -> rev_nat_r. rewrite -> IHl'. reflexivity. Qed.

Theorem app_assoc4 : forall l1 l2 l3 l4 : natlist,
  l1 ++ (l2 ++ (l3 ++ l4)) = ((l1 ++ l2) ++ l3) ++ l4.
Proof.
  intros l1 l2 l3 l4. rewrite -> app_assoc. rewrite -> app_assoc. reflexivity. Qed.

Lemma nonzeros_app : forall l1 l2 : natlist,
  nonzeros (l1 ++ l2) = (nonzeros l1) ++ (nonzeros l2).
Proof.
  intros l1 l2. induction l1 as [| n' l1'].
  - simpl. reflexivity.
  - destruct n'.
    + simpl. rewrite -> IHl1'. reflexivity.
    + simpl. rewrite -> IHl1'. reflexivity. Qed.

Exercise 8: 2 stars, standard (eqblist)

Fill in the definition of eqblist, which compares lists of numbers for equality. Prove that eqblist l l yields true for every list l.
Fixpoint eqblist (l1 l2 : natlist) : bool
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_eqblist1 :
(eqblist nil nil = true).
(
FILL IN HERE ) Admitted.
Example test_eqblist2 :
eqblist [1;2;3] [1;2;3] = true.
(
FILL IN HERE ) Admitted.
Example test_eqblist3 :
eqblist [1;2;3] [1;2;4] = false.
(
FILL IN HERE ) Admitted.
Theorem eqblist_refl : ∀l:natlist,
true = eqblist l l.
Proof.
(
FILL IN HERE *) Admitted.

解析:从测试的示例中可知函数” eqblist”是判断两个列表是否相等。在证明定理”eqblist_refl”时需要判断两个值是否相等,返回”true”或”false”,额外证明了定理beq_nat_n_n,forall n: nat, (n =? n) = true.在证明定理”eqblist_refl”时使用。

Fixpoint eqblist (l1 l2 : natlist) : bool :=
  match l1 with
  | nil => match l2 with 
           | nil => true
           | h2 :: t2 => false
           end
  | h1 :: t1 => match l2 with
                | nil => false
                | h2 :: t2 => match h1 =? h2 with 
                              | true => eqblist t1 t2
                              | false => false
                              end
                end
  end.

Example test_eqblist1 :
  (eqblist nil nil = true).
Proof. reflexivity.  Qed.

Example test_eqblist2 :
  eqblist [1;2;3] [1;2;3] = true.
Proof. reflexivity.  Qed.

Example test_eqblist3 :
  eqblist [1;2;3] [1;2;4] = false.
Proof. reflexivity.  Qed.

Theorem beq_nat_n_n : forall n: nat,
  (n =? n) = true.
Proof.
  intros n. induction n as [| n'].
  - simpl. reflexivity.
  - simpl. rewrite -> IHn'. reflexivity. Qed.

Theorem eqblist_refl : forall l:natlist,
  true = eqblist l l.
Proof.
  intros l. induction l as [| n' l'].
  - simpl. reflexivity.
  - simpl. rewrite <- IHl'. rewrite -> beq_nat_n_n. reflexivity. Qed.

Exercise 9: 1 star, standard (count_member_nonzero)

Theorem count_member_nonzero : ∀(s : bag),
1 <=? (count 1 (1 :: s)) = true.
Proof.
(* FILL IN HERE *) Admitted.

解析:简单使用归纳的方式即可完成证明。

Theorem count_member_nonzero : forall (s : bag),
  1 <=? (count 1 (1 :: s)) = true.
Proof.
  intros s. induction s as [| n s'].
  - simpl. reflexivity.
  - simpl. reflexivity. Qed.

Exercise 10: 3 stars, advanced (remove_does_not_increase_count)

Theorem remove_does_not_increase_count: ∀(s : bag),
(count 0 (remove_one 0 s)) <=? (count 0 s) = true.
Proof.
(* FILL IN HERE *) Admitted.

解析:从函数”count”的定义中可知,定理应该是正确的,采用归纳的方式,在证明过程中应用到示例中证明过的定理leb_n_Sn : forall n, n <=? (S n) = true.即可完成证明。

Theorem remove_does_not_increase_count: forall (s : bag),
  (count 0 (remove_one 0 s)) <=? (count 0 s) = true.
Proof.
  intros s. induction s as [| n s'].
  - simpl. reflexivity.
  - destruct n.
    + simpl. rewrite leb_n_Sn. reflexivity.
    + simpl. rewrite IHs'. reflexivity. Qed.

Exercise 11: 4 stars, advanced (rev_injective)

Prove that the rev function is injective — that is,
∀(l1 l2 : natlist), rev l1 = rev l2 → l1 = l2.

解析:根据描述,写出定理rev_injective: forall (l1 l2 : natlist), rev l1 = rev l2 -> l1 = l2.应用前面在联系7中证明过的定理” rev_involutive”即可完成证明。

Theorem rev_injective: forall (l1 l2 : natlist), 
  rev l1 = rev l2 -> l1 = l2.
Proof.
  intros. rewrite <- (rev_involutive l1), H. apply rev_involutive. Qed.

Exercise12: 2 stars, standard (hd_error)

Using the same idea, fix the hd function from earlier so we don’t have to pass a default element for the nil case.
Definition hd_error (l : natlist) : natoption
(* REPLACE THIS LINE WITH “:= your_definition .” ). Admitted.
Example test_hd_error1 : hd_error [] = None.
(
FILL IN HERE ) Admitted.
Example test_hd_error2 : hd_error [1] = Some 1.
(
FILL IN HERE ) Admitted.
Example test_hd_error3 : hd_error [5;6] = Some 5.
(
FILL IN HERE *) Admitted.

解析:比较简单,使用match方法,分情况给出结果即可。

Definition hd_error (l : natlist) : natoption :=
  match l with
   | nil => None
   | h :: t => Some h
  end.

Example test_hd_error1 : hd_error [] = None.
Proof. reflexivity. Qed.
Example test_hd_error2 : hd_error [1] = Some 1.
Proof. reflexivity. Qed.
Example test_hd_error3 : hd_error [5;6] = Some 5.
Proof. reflexivity. Qed.

Exercise13: 1 star, standard, optional (option_elim_hd)

This exercise relates your new hd_error to the old hd.
Theorem option_elim_hd : ∀(l:natlist) (default:nat),
hd default l = option_elim default (hd_error l).
Proof.
(* FILL IN HERE *) Admitted.

解析:对列表进行destruct分类验证,使用destruct l as [| n l’]即可。Destruct与induction最主要的区别是induction采用数学归纳法的验证。而destruct就是简单的分为两类验证。

Theorem option_elim_hd : forall (l:natlist) (default:nat),
  hd default l = option_elim default (hd_error l).
Proof.
  intros l default. destruct l as [| n l'].
  - simpl. reflexivity.
  - simpl. reflexivity. Qed.

Exercise14: 1 star, standard (eqb_id_refl)

Theorem eqb_id_refl : ∀x, true = eqb_id x x.
Proof.
(* FILL IN HERE *) Admitted.

解析:对n进行归纳验证即可。

Theorem beq_nat_n_n : forall n: nat,
  (n =? n) = true.
Proof.
  intros n. induction n as [| n'].
  - simpl. reflexivity.
  - simpl. rewrite -> IHn'. reflexivity. Qed.

Exercise15: 1 star, standard (update_eq)

Theorem update_eq :
∀(d : partial_map) (x : id) (v: nat),
find x (update d x v) = Some v.
Proof.
(* FILL IN HERE *) Admitted.

解析:比较简单,在证明过程中,采用重写策略。

Theorem update_neq :
  forall (d : partial_map) (x y : id) (o: nat),
    eqb_id x y = false -> find x (update d y o) = find x d.
Proof.
  intros d x y o. intros H. simpl. rewrite H. reflexivity. Qed.

Exercise16: 1 star, standard (update_neq)

Theorem update_neq :
∀(d : partial_map) (x y : id) (o: nat),
eqb_id x y = false → find x (update d y o) = find x d.
Proof.

解析:化简、重写即可。

Theorem update_neq :
  forall (d : partial_map) (x y : id) (o: nat),
    eqb_id x y = false -> find x (update d y o) = find x d.
Proof.
  intros d x y o. intros H. simpl. rewrite H. reflexivity. Qed.
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值