Require Import Coq.ZArith.ZArith. Require Import Coq.Bool.Bool. Require Import Coq.Lists.List. Require Import Coq.Classes.RelationClasses. Require Import Coq.Classes.Morphisms. Require Import Coq.micromega.Psatz. Require Import Permutation. Require Import String. From AUXLib Require Import int_auto Axioms Feq Idents List_lemma VMap. Require Import SetsClass.SetsClass. Import SetsNotation. From SimpleC.SL Require Import CommonAssertion Mem SeparationLogic IntLib. Require Import Logic.LogicGenerator.demo932.Interface. Local Open Scope Z_scope. Local Open Scope sets. Import ListNotations. Local Open Scope list. Require Import String. Local Open Scope string. Import naive_C_Rules. Local Open Scope sac. Module Aux. Lemma Zpow_add_1: forall (a b: Z), a >= 0 -> b >= 0 -> a ^ (b + 1) = a ^ b * a. Proof. intros. rewrite (Z.pow_add_r a b 1); lia. Qed. Lemma Z_of_nat_succ: forall (n: nat), Z.of_nat (S n) = Z.of_nat n + 1. Lemma Zdiv_mod_pow: forall (n a b: Z), a > 0 -> b >= 0 -> n >= 0 -> (n / a) mod (a ^ b) = (n mod (a ^ (b + 1))) / a. Proof. intros. pose proof (Z_div_mod_eq_full n (a ^ (b + 1))). remember (n / (a ^ (b + 1))) as q eqn:Hq. remember (n mod a ^ (b + 1)) as rem eqn:Hrem. assert (n / a = a ^ b * q + rem / a). { rewrite H2. rewrite Zpow_add_1; try lia. pose proof (Z_div_plus_full_l (a ^ b * q) a rem ltac:(lia)). assert (a ^ b * q * a + rem = a ^ b * a * q + rem). { lia. } rewrite H4 in H3. tauto. } apply Znumtheory.Zdivide_mod_minus. + pose proof (Z.mod_bound_pos n (a ^ (b + 1)) ltac:(lia) (Z.pow_pos_nonneg a (b + 1) ltac:(lia) ltac:(lia))). rewrite <-Hrem in H4. rewrite Zpow_add_1 in H4; try lia. pose proof (Z.div_lt_upper_bound rem a (a ^ b) ltac:(lia) ltac:(lia)). split; try lia. apply (Z_div_pos rem a ltac:(lia) ltac:(lia)). + unfold Z.divide. exists q. lia. Qed. End Aux.