#include using namespace std; using ll = long long; using Vi = vector; using Pii = pair; #define mp make_pair #define pb push_back #define x first #define y second #define rep(i,b,e) for(int i = (b); i < (e); i++) #define each(a, x) for(auto& a : (x)) #define all(x) (x).begin(),(x).end() #define sz(x) int((x).size()) #define tem template #define pri(x,y)tem auto operator<<(t& o, u a)->decltype(x,o) { o << y; return o; } pri(a.print(), "{"; a.print(); "}"); pri(a.y, "(" << a.x << ", " << a.y << ")"); pri(all(a), "["; auto d=""; for (auto i : a) (o << d << i, d = ", "); o << "]"); void DD(...) {} tem void DD(t s, u a, w... k) { for (int b = 44; *s && *s - b; cerr << *s++) b += ((*s == 41) - (*s == 40)) * 88; cerr << ": " << a << *s++; DD(s, k...); } tem vector span(const t* a, u n) { return {a, a+n}; } #ifdef LOC #define deb(...) (DD("[,\b :] "#__VA_ARGS__, __LINE__, __VA_ARGS__), cerr << endl) #else #define deb(...) #endif #define DBP(...) void print() { DD(#__VA_ARGS__, __VA_ARGS__); } const ll mod = 1e9 + 7; int gcd(int a, int b) { while (b) { a %= b; swap(a, b); } return a; } struct GCD { vector V, pom; void insert(int a, int pos) { pom.pb({a, pos}); for (Pii p : V) { int x = gcd(a, p.x); if (x == pom.back().x) { pom.back().y = p.y; } else { pom.pb({x, p.y}); } } V = pom; pom.clear(); } }; struct Tree { int base = 1; Vi lazySet, maks; vector sum; Tree (int n) { while (base < n+3) base *= 2; lazySet.resize(2*base); maks.resize(2*base); sum.resize(2*base); } void apply(int a, int nl, int nr, int x) { lazySet[a] = x; maks[a] = x; sum[a] = (ll)x * (nr - nl + 1); } void update(int a) { if (a >= base) return; maks[a] = max(maks[2*a], maks[2*a + 1]); sum[a] = sum[2*a] + sum[2*a + 1]; } void push(int a, int nl, int nr) { if (lazySet[a]) { int mid = (nl + nr) / 2; apply(2*a, nl, mid, lazySet[a]); apply(2*a + 1, mid + 1, nr, lazySet[a]); lazySet[a] = 0; } } void setVal(int a, int nl, int nr, int ql, int qr, int x) { if (nr < ql || qr < nl) return; if (ql <= nl && nr <= qr) { apply(a, nl, nr, x); return; } int mid = (nl + nr) / 2; push(a, nl, nr); setVal(2*a, nl, mid, ql, qr, x); setVal(2*a+1, mid+1, nr, ql, qr, x); update(a); } ll getSum(int a, int nl, int nr, int ql, int qr) { if (nr < ql || qr < nl) return 0; if (ql <= nl && nr <= qr) { return sum[a]; } int mid = (nl + nr) / 2; push(a, nl, nr); ll res = 0; res += getSum(2*a, nl, mid, ql, qr); res += getSum(2*a+1, mid+1, nr, ql, qr); update(a); return res; } int find(int x) { int a = 1; int nl = 1, nr = base; while (a < base) { push(a, nl, nr); int mid = (nl + nr) / 2; if (maks[2*a+1] >= x ) { a = 2*a + 1; nl = mid+1; } else if(maks[2*a] >= x) { a = 2 * a; nr = mid; } else return 0; } return nl; } void insert(int l, int r, int x) { if (l > r) return; setVal(1, 1, base, l, r, x); } ll query(int l, int r) { return getSum(1, 1, base, l, r); } }; void solve() { int n; cin >> n; GCD G; Tree tree(n+10); ll res = 0; for (int i = 1; i <= n; i++) { int x; cin >> x; G.insert(x, i); int pos = tree.find(x); tree.insert(pos+1, i, x); // for (Pii p : G.V) { // cout << p.x << " " << p.y << endl; // } // cout << endl; // for (int j = 1; j <= n; j++) { // cout << j << ":" << tree.query(j,j) << " "; // } // cout << endl; // deb(pos); // cout << endl; int lastBegin = i + 1; for (Pii p : G.V) { ll q = tree.query(p.y, lastBegin - 1); q %= mod; res += (ll)p.x * q; res%= mod; lastBegin = p.y; } } cout << res << endl; } int main() { cin.sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(12); solve(); return 0; }