#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#include <atcoder/all>
#define ll long long
#define ull unsigned long long
//roop
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<n;i++)
#define repi(i,a,b) for(int i=a;i<b;i++)
#define repa(i,n) for(auto i : n)
#define repad(i,n) for(auto &i:n)
#define all(a) a.begin(),a.end()
#define INFint 2147483640
#define INFLL (long long)1 << 60
#define mint modint1000000007
#define mint9 modint998244353
using namespace std;
using namespace atcoder;
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
std::ostream::sentry s(dest);
if (s) {
__uint128_t tmp = value < 0 ? -value : value;
char buffer[128];
char *d = std::end(buffer);
do {
--d;
*d = "0123456789"[tmp % 10];
tmp /= 10;
} while (tmp != 0);
if (value < 0) {
--d;
*d = '-';
}
int len = std::end(buffer) - d;
if (dest.rdbuf()->sputn(d, len) != len) {
dest.setstate(std::ios_base::badbit);
}
}
return dest;
}
/*2進数配列+1*/
/*vector<int> twoadd(vector<int> v, int N){
v[N-1]+=1;
int ind = N-1;
int j=N-1;
for(j=N-1;j>=1;j--){
if(v[j]>1){
v[j-1]+=1;
v[j]=0;
}
}
return v;
}
/*フィボナッチ*/
long long fibonatti(long long d){
long long count = 0;
long long f1 = 1;
long long f2 = 1;/*ここを変える*/
long long temp;
if(d == 1){
count = f1;
}else if(d == 2){
count = f2;
}else if(d==0){
count = 1;
}else{
for(int i=0;i<d-2;i++){
temp = f1+f2;
f1 = f2;
f2 = temp;
}
count = temp;
}
return count;
}
/*最大公約数*/
unsigned long long GCD(long long L,long long R){
if(L>R){
long long temp=R;
R = L;
L = temp;
}
unsigned long long pp=0,ppt=0;
unsigned long long ans=0;
if(R%L==0){
ans = L;
}else{
while(true){
ppt = pp;
pp=R%L;
if(pp == 0){
ans = ppt;
break;
}
R = L;
L = pp;
}
}
return ans;
}
/*最小公倍数*/
unsigned long long LCM(long long L,long long R){
unsigned long long ans;
unsigned long long gcd = GCD(L,R);
ans = (L/gcd)*R;
return ans;
}
/*Combination set*/
#define mod 1000000007
//#define mod 998244353
#define maxcomb 20000/*大きいものを求めるときはここを変える*/
vector<long long> fc(maxcomb+1);
vector<long long> ifc(maxcomb+1);
long long modpow(long long x,long long n){
long long ans = 1;
while(n > 0){
if(n & 1) {
ans = ans*x%mod;
}
x = x*x%mod;
n >>= 1;
}
return ans;
}
void Comb(){
fc[0]= 1;
ifc[0]=1;
for(long long i=0;i<maxcomb;i++){
fc[i+1] = fc[i]*(i+1)%mod;//n!(mod)
ifc[i+1] = ifc[i]*modpow(i+1,mod-2)%mod;//k!^{M-2} (mod)
}
}
/*Required Comb()*/
unsigned long long Combination(long long L,long long R){
unsigned long long up=1,ans;
//Conb();
if(L==0&&R==0){
return 1;
}else if(L<R||L<0){
return 0;
}else{
long long t = ifc[L-R]*ifc[R]%mod;
ans = t*fc[L]%mod;
}
return ans;
}
/*Combination set ここまで*/
/*素数判定*/
bool isPrime(int x){
int i;
if(x < 2){
return 0;
}else if(x == 2){
return 1;
}
if(x%2 == 0) {
return 0;
}
for(i = 3; i*i <= x; i += 2){
if(x%i == 0){
return 0;
}
}
return 1;
}
/*桁和*/
int digsum(int n) {
int res = 0;
while(n > 0) {
res += n%10;
n /= 10;
}
return res;
}
/*約数の数*/
long long countdivisor(long long K){
long long N = sqrt(K);
bool b = false;
if(sqrt(K)-N==0){
b= true;
}
long long count =0;
for(int i=0;i<N;i++){
if(K%(i+1)==0){
count++;
}
}
if(b==false){
count *= 2;
}else{
count = (count-1)*2+1;
}
return count;
}
/*約数列挙*/
vector<long long> Alldivisor(long long n){
vector<long long> ret;
for(int i=1;i*i<=n;i++){
if(n%i == 0){
ret.push_back(i);
if(i != 1 && i*i != n){
ret.push_back(n/i);
}
}
}
return ret;
}
/**/
template <typename T>
vector<pair<T, T>> prime_factor(T n) {
vector<pair<T, T>> ret;
for (T i = 2; i * i <= n; i++) {
T tmp = 0;
while (n % i == 0) {
tmp++;
n /= i;
}
if(tmp!=0) ret.push_back(make_pair(i, tmp));
}
if (n != 1) ret.push_back(make_pair(n, 1));
return ret;
}
/*特定の文字カウント*/
int stringcount(string s,char c){
return count(s.cbegin(),s.cend(),c);
}
/*Graph*/
using Graph = vector<vector<int>>; //グラフ型
/*vector<int> first_order; //行きがけ順
vector<int> last_order; //帰りがけ順 */
/*重みなし有向*/
Graph WeightlessGraph(int N,int M){
Graph G(N);
//vector<bool> m(N,false);
for(int i=0;i<M;i++){
int a,b;
cin >> a >> b;
G[a-1].push_back(b-1);
}
return G;
}
/*重みなし無向*/
Graph WeightlessNoDirectionGraph(int N,int M){
Graph G(N);
for(int i=0;i<M;i++){
int a,b;
cin >> a >> b;
G[a-1].push_back(b-1);
G[b-1].push_back(a-1);
}
return G;
}
/*深さ優先探索*/
vector<bool> seen;
//vector<ll> ans;
void dfs(const Graph &G, int s,int p){
seen[s]=true;
/*if(p!=-1){
ans[s]+=ans[p];
}*/
for(auto next_v:G[s]){
if(seen[next_v]){
continue;
}
dfs(G,next_v,s);
}
}
/*1以外の素因数の個数*/
long long prime_counter(long n) {
long long count=0;
bool ch = false;
for (long i = 2; i * i <= n; i++) {
long long tmp = 0;
while (n % i == 0) {
tmp++;
n /= i;
ch = true;
}
if(ch == true) count++;
ch = false;
}
if (n != 1) count++;
return count;
}
long long divisor(long long n){
int i=sqrt(n);
while(true){
if(n%i == 0){
return i;
}
i--;
}
}
long long modpow1(long long x,long long n,long long md){
long long ans = 1;
while(n > 0){
if(n & 1) {
ans = ans*x%md;
}
x = x*x%md;
n >>= 1;
}
return ans;
}
/*bit全探索用*/
vector<int> bitlevel;
void levelup(int N){
bitlevel[N-1]+=1;
int ind = N-1;
int j=N-1;
for(j=N-1;j>=1;j--){
//cout << j << endl;
if(bitlevel[j]>1){
bitlevel[j-1]+=1;
bitlevel[j]=0;
}
}
}
int vector_finder(std::vector<int> vec, int number) {
auto itr = std::find(vec.begin(), vec.end(), number);
size_t index = std::distance( vec.begin(), itr );
if (index != vec.size()) { // 発見できたとき
return 1;
}
else { // 発見できなかったとき
return 0;
}
}
vector<ll> a;
int binary_search(int l,int r,ll k){
int mid = (l+r)/2;
if(l>=r) return mid;
if(a[mid]<k) return binary_search(mid+1,r,k);
else return binary_search(l,mid,k);
}
struct UnionFind {
vector<int> par; // par[i]:iの親の番号 (例) par[3] = 2 : 3の親が2
vector<ll> siz;
UnionFind(int N) : par(N) { //最初は全てが根であるとして初期化
for(int i = 0; i < N; i++) par[i] = i;
siz.assign(N,1);
}
int root(int x) { // データxが属する木の根を再帰で得る:root(x) = {xの木の根}
if (par[x] == x) return x;
return par[x] = root(par[x]);
}
void unite(int x, int y) { // xとyの木を併合
int rx = root(x); //xの根をrx
int ry = root(y); //yの根をry
if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
//cout << par[y] << endl;
//cout << siz[ry] << " " << siz[rx] << endl;
siz[ry] += siz[rx];
//cout << siz[ry] << endl;
par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時:xの根rxをyの根ryにつける
}
bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
int rx = root(x);
int ry = root(y);
return rx == ry;
}
ll size(ll x){
return siz[root(x)];
}
};
/*座圧*/
void compressor(vector<int> &a){
set<int> s(all(a));
map<int,int> d;
int cnt = 0;
repa(x,s) d[x] = cnt++;
repad(x,a) x = d[x];
}
struct dpair{
ll a,b;
bool operator < (const dpair &p) const{
if(p.a!= a) return p.a > a;
else return p.b < b;
}
bool operator == (const dpair &p) const{
if(p.a==a&&p.b==b) return true;
else return false;
}
};
/*segment tree*/
mint9 op(mint9 a,mint9 b){return a+b;}
mint9 e(){return 0LL;}
vector<ll> LISLEN;
vector<ll> LISDP;
template <typename T>
void LIS(int n,vector<T> a){
LISLEN.assign(n,0);
LISDP.assign(n,INFLL);
for(int i=0;i<n;i++){
int itr = lower_bound(all(LISDP),a[i])-LISDP.begin();
LISDP[itr] = a[i];
LISLEN[i] = itr+1;
}
}
struct Edges
{
ll from, to, weight;
// コストの大小で順序定義
bool operator<(const Edges& o) const {
return weight < o.weight;
}
};
struct KGraph
{
int n; // 頂点数
vector<Edges> es; // 辺集合
void input(int n,int m){
Edges e;
cin >> e.from >> e.to >> e.weight;
e.from--,e.to--;
es.push_back(e);
}
//map<int,bool> us;
// クラスカル法で無向最小全域木のコストの和を計算する
// グラフが非連結のときは最小全域森のコストの和となる
ll kruskal() {
// コストが小さい順にソート
sort(es.begin(), es.end());
UnionFind uf(n);
ll min_cost = 0;
rep(ei, es.size()) {
Edges& e = es[ei];
if (!uf.same(e.from, e.to)||e.weight<0) {
// 辺を追加しても閉路ができないなら、その辺を採用する
min_cost += e.weight;
//us[ei] = true;
uf.unite(e.from, e.to);
}
}
return min_cost;
}
};
struct Edge{
int to; //辺の行き先
int weight; //辺の重み
Edge(int t,int w):to(t),weight(w){}
};
using WGraph = vector<vector<Edge>>;
WGraph WeightGraph(int N,int M){
WGraph G(N+1);
for(int i=0;i<M;i++){
int from, to ,weight;
cin >> from >> to >> weight;
G[from].push_back(Edge(to,weight));
}
return G;
}
template <class Abel> struct BIT {
vector<Abel> dat;
Abel UNITY_SUM = 0; // to be set
/* [1, n] */
BIT(int n) { init(n); }
void init(int n) {
dat.resize(n + 1);
for (int i = 0; i < (int)dat.size(); ++i) dat[i] = UNITY_SUM;
}
/* a is 1-indexed */
inline void add(int a, Abel x) {
for (int i = a; i < (int)dat.size(); i += i & -i)
dat[i] = dat[i] + x;
}
/* [1, a], a is 1-indexed */
inline Abel sum(int a) {
Abel res = UNITY_SUM;
for (int i = a; i > 0; i -= i & -i)
res = res + dat[i];
return res;
}
/* [a, b), a and b are 1-indexed */
inline Abel sum(int a, int b) {
return sum(b - 1) - sum(a - 1);
}
/* k-th number (k is 0-indexed) */
int get(long long k) {
++k;
int res = 0;
int N = 1; while (N < (int)dat.size()) N *= 2;
for (int i = N / 2; i > 0; i /= 2) {
if (res + i < (int)dat.size() && dat[res + i] < k) {
k = k - dat[res + i];
res = res + i;
}
}
return res + 1;
}
};
/*長さ1の配列に対してif(a[0]==a[1])などとやると、atcoderのジャッジではtrueとなる,手元ではfalse*/
/*ここから*/
int main() {
int n;
cin >> n;
vector<int> a(n);
rep(i,n){
cin >> a[i];
}
mint9 div = 1;
mint9 ans = 0;
compressor(a);
segtree<mint9,op,e> seg(n+1);
rep(i,n){
mint9 k = seg.prod(0,a[i]+1);
k *= div;
div *= 2;
ans += k;
seg.set(a[i],seg.prod(a[i],a[i]+1)+1/div);
}
cout << ans.val() << endl;
return 0;
}
/*REの時vectorのoverflow確認*/