/**
 * @author derrick20
 */

import java.io.*;
import java.util.*;

public class TopScorer {
    public static void main(String[] args) throws Exception {
        FastScanner sc = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);

        int P = sc.nextInt();
        int S = sc.nextInt();
        int R = sc.nextInt();
        // it should go up to s + p - 1, 5099, but let's be safe
        int MAX = 5100; // todo change this!
        fact = new long[MAX + 1];
        invFact = new long[MAX + 1];
        fact[0] = 1;
        invFact[0] = 1;
        for (int i = 1; i <= MAX; i++) {
            fact[i] = ((long) i * fact[i - 1]) % mod;
            invFact[i] = inv(fact[i]);
        }

        if (P == 1) {
            out.println(1);
        } else {
            // O(SP^2) = 5*10^7
            long wins = 0;
            long total = 0;
            for (int x = R; x <= S; x++) {
                // l = group that gets x
                // the remaining players P - 1 - l must get < x.
                for (int l = 0; P - 1 - l >= 0 && S - x - l * x >= 0; l++) {
                    int players = P - 1 - l;
                    int balls = S - x - l * x;
//                    System.out.println("Forced " + l + " other players to have exactly " + x + " balls");
//                    System.out.println("Remaining: players = " + players + " balls = " + balls);
                    long prob = (choose(P - 1, l) * f(players, balls, x)) % mod;
                    // prob of having this number of x's for players, then given
                    // that, the probability of winning is uniform among all x players
                    long contrib = (inv(l + 1) * prob) % mod;
                    wins = (wins + contrib) % mod;
//                    System.out.println("Prob: " + prob + " Contrib: " + contrib);
//                    System.out.println();
                }
                long ways = choose(S - x + P - 2, P - 2);
//                System.out.println("Ways for x = " + x + " = " + ways);
//                System.out.println("----------");
                total = (total + ways) % mod;
            }
            // we have now counted the number of winning states (scaling
            // with the f function). The probability is this divided by total
            // states.
            long prob = (wins * inv(total)) % mod;
            out.println(prob);
        }
        out.close();
    }

    // todo SET THE MOD
    static long mod = 998244353;
    static long[] fact, invFact;

    // f returns probability that with these parameters, we get an assignment
    // where all have < x balls.
    static long f(int players, int balls, int x) {
        // if there are no players, there MUST BE only 1 way.
        if (players == 0) {
//            ASSERT(balls <= x, "Gave impossible amt");
            /**
             * Key issue: add in logic for simple cases. If 0 players. it makes
             * no sense to give a positive number of balls, so 0 ways. If zero,
             * there is 1 way, i.e. do nothing.
             */
            return (balls == 0) ? 1 : 0;
        }
        long total = choose(balls + players - 1, players - 1);
        long complement = 0;
        int sign = 1;
        for (int k = 1; k <= players && balls - k * x >= 0; k++) {
            long amt = (choose(players, k) * choose(balls - k * x + players - 1, players - 1)) % mod;
            complement = (complement + sign * amt) % mod;
            sign *= -1;
        }
//        System.out.println("Ways for (players, balls) = " + players + " " + balls + ": Total " + total + ", Complement: " + complement);
        long ans = (total - complement + mod) % mod;
//        ans = (ans * inv(total)) % mod; // probability
        return ans;
    }

    static long choose(int n, int k) {
        ASSERT(k <= n, "Invalid choose");
        long ans = (fact[n] * invFact[n - k]) % mod;
        return (ans * invFact[k]) % mod;
    }

    static long inv(long x) {
        return fastExpo(x, mod - 2);
    }

    static long fastExpo(long x, long k) {
        long ans = 1;
        long bit = x;
        while (k > 0) {
            if (k % 2 == 1) {
                ans = (bit * ans) % mod;
            }
            bit = (bit * bit) % mod;
            k /= 2;
        }
        return ans;
    }

    static class FastScanner {
        private int BS = 1 << 16;
        private char NC = (char) 0;
        private byte[] buf = new byte[BS];
        private int bId = 0, size = 0;
        private char c = NC;
        private double cnt = 1;
        private BufferedInputStream in;

        public FastScanner() {
            in = new BufferedInputStream(System.in, BS);
        }

        public FastScanner(String s) {
            try {
                in = new BufferedInputStream(new FileInputStream(new File(s)), BS);
            } catch (Exception e) {
                in = new BufferedInputStream(System.in, BS);
            }
        }

        private char getChar() {
            while (bId == size) {
                try {
                    size = in.read(buf);
                } catch (Exception e) {
                    return NC;
                }
                if (size == -1) return NC;
                bId = 0;
            }
            return (char) buf[bId++];
        }

        public int nextInt() {
            return (int) nextLong();
        }

        public int[] nextInts(int N) {
            int[] res = new int[N];
            for (int i = 0; i < N; i++) {
                res[i] = (int) nextLong();
            }
            return res;
        }

        public long[] nextLongs(int N) {
            long[] res = new long[N];
            for (int i = 0; i < N; i++) {
                res[i] = nextLong();
            }
            return res;
        }

        public long nextLong() {
            cnt = 1;
            boolean neg = false;
            if (c == NC) c = getChar();
            for (; (c < '0' || c > '9'); c = getChar()) {
                if (c == '-') neg = true;
            }
            long res = 0;
            for (; c >= '0' && c <= '9'; c = getChar()) {
                res = (res << 3) + (res << 1) + c - '0';
                cnt *= 10;
            }
            return neg ? -res : res;
        }

        public double nextDouble() {
            double cur = nextLong();
            return c != '.' ? cur : cur + nextLong() / cnt;
        }

        public double[] nextDoubles(int N) {
            double[] res = new double[N];
            for (int i = 0; i < N; i++) {
                res[i] = nextDouble();
            }
            return res;
        }

        public String next() {
            StringBuilder res = new StringBuilder();
            while (c <= 32) c = getChar();
            while (c > 32) {
                res.append(c);
                c = getChar();
            }
            return res.toString();
        }

        public String nextLine() {
            StringBuilder res = new StringBuilder();
            while (c <= 32) c = getChar();
            while (c != '\n') {
                res.append(c);
                c = getChar();
            }
            return res.toString();
        }

        public boolean hasNext() {
            if (c > 32) return true;
            while (true) {
                c = getChar();
                if (c == NC) return false;
                else if (c > 32) return true;
            }
        }
    }

    static void ASSERT(boolean assertion, String message) {
        if (!assertion) throw new AssertionError(message);
    }
}


import java.io.*;
import java.util.*;
public class B {
    public static void main(String[] args)throws Throwable {
        MyScanner sc=new MyScanner();
        PrintWriter pw=new PrintWriter(System.out);

        long n=sc.nextInt();

//        if(n<15)
//            pw.println(solve(n));
//        else
//            pw.println(solve(15)+(n-15)*49);

        boolean [][] ok=new boolean [10][50];
        for(boolean [] x : ok)
            Arrays.fill(x,true);
        for(int i=0;i<9;i++)
            for(int j=0;j<49;j++)
                for(int i2=0;i2<9;i2++)
                    for(int j2=0;j2<49;j2++) {
                        int x = i * 4 + j * 9 - i2 * 4 - j2 * 9;
                        if (x > 0 && x % 49 == 0)
                            ok[i][j] = false;
                    }
        long ans=0;
        for(int i=0;i<9;i++)
            for(int j=0;j<49;j++)
                if(ok[i][j] && n>=i+j)
                    ans+=n-i-j+1;
        pw.println(ans);
        pw.flush();
        pw.close();
    }

    static int solve(long n){
        HashSet<Long> set=new HashSet<>();
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n-i;j++)
                for(int k=0;k<=n-i-j;k++)
                    set.add(i*50+j*10+k*5+n-i-j-k);
        return set.size();
    }

    static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {while (st == null || !st.hasMoreElements()) {
            try {st = new StringTokenizer(br.readLine());}
            catch (IOException e) {e.printStackTrace();}}
            return st.nextToken();}
        int nextInt() {return Integer.parseInt(next());}
        long nextLong() {return Long.parseLong(next());}
        double nextDouble() {return Double.parseDouble(next());}
        String nextLine(){String str = "";
            try {str = br.readLine();}
            catch (IOException e) {e.printStackTrace();}
            return str;}
    }
}


// Don't place your source in a package
import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;

 /*

 6666666666666			 6666666666666
 6						 6
 6						 6
 6						 6
 6						 6
 6                       6
 6666666666666           6666666666666
 6		     6           6		     6
 6			 6	         6			 6
 6			 6           6			 6
 6		     6	         6		     6
 6666666666666           6666666666666

 */

// Please name your class Main
public class Main {

	//static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    /*static int read() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }
    static String readString() throws IOException {
        in.nextToken();
        return in.sval;
	}*/

	static Scanner in = new Scanner(System.in);

	public static void main (String[] args) throws java.lang.Exception {

		//InputReader in = new InputReader(System.in);
		PrintWriter out = new PrintWriter(System.out);

		int T=1;

		for(int t=0;t<T;t++){
			int K=Int();
			long F[]=new long[6];
			for(int i=0;i<6;i++){
				F[i]=Int();
			}

			int q=Int();
			int W=Int();

			Solution sol=new Solution();
			sol.solution(K,F,W);
		}

		out.flush();
	}

	public static int Int(){
		return in.nextInt();
	}
	public static String Str(){
		return in.next();
	}
}

class Solution{
	//constant variable
	final int MAX=Integer.MAX_VALUE;
	final int MIN=Integer.MIN_VALUE;
	//Set<Integer>adjecent[];
	//////////////////////////////

	public void solution(int K,long F[],int W){
		long res=0;
		int ten[]=new int[]{1,10,100,1000,10000,100000};

		//0-1 knapsack, creating items
		List<Item>A=new ArrayList<>();

		K--;//extra number

		if(K==0){
			String num=(W)+"";
			StringBuilder str=new StringBuilder(num);
			num=str.reverse().toString();
			long score=0;
			for(int k=0;k<num.length();k++){
				int d=num.charAt(k)-'0';
				if(d%3==0){
					score+=(F[k]*(d/3));
				}
			}
			msg(score+"");
			return;
		}

		for(int i=0;i<6;i++){//1 10 100 1000 10000 10000
			long weight=ten[i]*3;//single weight
			int cur=0;
			for(int j=0;j<32;j++){
				int go=1<<j;
				if(cur+go>=(3*K)){
					long remain=3*K-cur;
					Item item=new Item(weight*remain,F[i]*remain,i);
					A.add(item);
					break;
				}
				Item item=new Item(weight*(1<<j),F[i]*(1<<j),i);
				cur+=(1<<j);
				A.add(item);
			}
		}

		long pre[]=new long[W+1];
		long dp[]=new long[W+1];
		Arrays.fill(pre,-1);
		pre[0]=0;

		for(int i=1;i<A.size();i++){
			Item item=A.get(i-1);
			dp=new long[W+1];
			Arrays.fill(dp,-1);
			dp[0]=0;
			for(int j=1;j<dp.length;j++){
				dp[j]=Math.max(dp[j],pre[j]);
				long w=(item.w);
				long val=item.val;
				if(j<w||pre[(int)(j-w)]==-1){
					continue;
				}
				dp[j]=Math.max(dp[j],pre[(int)(j-w)]+val);
				String num=(W-j)+"";
				StringBuilder str=new StringBuilder(num);
				num=str.reverse().toString();
				long score=0;
				for(int k=0;k<num.length();k++){
					int d=num.charAt(k)-'0';
					if(d%3==0){
						score+=(F[k]*(d/3));
					}
				}
				res=Math.max(res,dp[j]+score);

			}
			pre=dp;
		}

		msg(res+"");

	}

	class Item{
		long w=0;
		long val=0;
		int group;
		public Item(long w,long val,int group){
			this.w=w;
			this.val=val;
			this.group=group;
		}

		public String toString(){
			return w+"  "+val+"   "+group+"  \n";
		}
	}

	public void swap(int A[],int l,int r){
		int t=A[l];
		A[l]=A[r];
		A[r]=t;
	}

	public long C(long fact[],int i,int j){ // C(20,3)=20!/(17!*3!)
		// take   a/b     where a=20!  b=17!*3!
		if(j>i)return 0;
		if(j==0)return 1;
		long mod=1000000007;
		long a=fact[i];
		long b=((fact[i-j]%mod)*(fact[j]%mod))%mod;
		BigInteger B= BigInteger.valueOf(b);
		long binverse=B.modInverse(BigInteger.valueOf(mod)).longValue();
		return ((a)*(binverse%mod))%mod;
	}

	//map operation
	public void put(Map<Integer,Integer>map,int i){
		if(!map.containsKey(i))map.put(i,0);
		map.put(i,map.get(i)+1);
	}

	public void delete(Map<Integer,Integer>map,int i){
		map.put(i,map.get(i)-1);
		if(map.get(i)==0)map.remove(i);
	}

	/*public void tarjan(int p,int r){
		if(cut)return;
		List<Integer>childs=adjecent[r];
		dis[r]=low[r]=time;
		time++;

		//core for tarjan
		int son=0;
		for(int c:childs){
			if(ban==c||c==p)continue;
			if(dis[c]==-1){
				son++;
				tarjan(r,c);
				low[r]=Math.min(low[r],low[c]);
				if((r==root&&son>1)||(low[c]>=dis[r]&&r!=root)){
					cut=true;
					return;
				}
			}else{
				if(c!=p){
					low[r]=Math.min(low[r],dis[c]);
				}
			}
		}

	}*/

	//helper function I would use
	public void remove(Map<Integer,Integer>map,int i){
		map.put(i,map.get(i)-1);
		if(map.get(i)==0)map.remove(i);
	}

	public void ascii(String s){
		for(char c:s.toCharArray()){
			System.out.print((c-'a')+" ");
		}
		msg("");
	}

	public int flip(int i){
		if(i==0)return 1;
		else return 0;
	}

	public boolean[] primes(int n){
		boolean A[]=new boolean[n+1];
		for(int i=2;i<=n;i++){
			if(A[i]==false){
				for(int j=i+i;j<=n;j+=i){
					A[j]=true;
				}
			}
		}
		return A;
	}

	public void msg(String s){
		System.out.println(s);
	}

	public void msg1(String s){
		System.out.print(s);
	}

	public int[] kmpPre(String p){
		int pre[]=new int[p.length()];
		int l=0,r=1;
		while(r<p.length()){
			if(p.charAt(l)==p.charAt(r)){
				pre[r]=l+1;
				l++;r++;
			}else{
				if(l==0)r++;
				else l=pre[l-1];
			}
		}
		return pre;
	}

	public boolean isP(String s){
		int l=0,r=s.length()-1;
		while(l<r){
			if(s.charAt(l)!=s.charAt(r))return false;
			l++;r--;
		}
		return true;
	}

	public int find(int nums[],int x){//union find => find method
		if(nums[x]==x)return x;
		int root=find(nums,nums[x]);
		nums[x]=root;
		return root;
	}

	public int get(int A[],int i){
		if(i<0||i>=A.length)return 0;
		return A[i];
	}
	public int[] copy1(int A[]){
		int a[]=new int[A.length];
		for(int i=0;i<a.length;i++)a[i]=A[i];
		return a;
	}

	public void print1(long A[]){
		for(long i:A)System.out.print(i+" ");
		System.out.println();
	}
	public void print2(int A[][]){
		for(int i=0;i<A.length;i++){
			for(int j=0;j<A[0].length;j++){
				System.out.print(A[i][j]+" ");
			}System.out.println();
		}
	}

	public int min(int a,int b){
		return Math.min(a,b);
	}

	public int[][] matrixdp(int[][] grid) {
        if(grid.length==0)return new int[][]{};
        int res[][]=new int[grid.length][grid[0].length];
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[0].length;j++){
                res[i][j]=grid[i][j]+get(res,i-1,j)+get(res,i,j-1)-get(res,i-1,j-1);
            }
        }
        return res;
    }

    public int get(int grid[][],int i,int j){
        if(i<0||j<0||i>=grid.length||j>=grid[0].length)return 0;
        return grid[i][j];
    }

	public int[] suffixArray(String s){
		int n=s.length();
		Suffix A[]=new Suffix[n];

		for(int i=0;i<n;i++){
			A[i]=new Suffix(i,s.charAt(i)-'a',0);
		}

		for(int i=0;i<n;i++){
			if(i==n-1){
				A[i].next=-1;
			}else{
				A[i].next=A[i+1].rank;
			}
		}
		Arrays.sort(A);

		for(int len=4;len<A.length*2;len<<=1){
			int in[]=new int[A.length];
			int rank=0;
			int pre=A[0].rank;
			A[0].rank=rank;
			in[A[0].index]=0;
			for(int i=1;i<A.length;i++){//rank for the first two letter
				if(A[i].rank==pre&&A[i].next==A[i-1].next){
					pre=A[i].rank;
					A[i].rank=rank;
				}else{
					pre=A[i].rank;
					A[i].rank=++rank;
				}
				in[A[i].index]=i;
			}

			for(int i=0;i<A.length;i++){
				int next=A[i].index+len/2;
				if(next>=A.length){
					A[i].next=-1;
				}else{
					A[i].next=A[in[next]].rank;
				}
			}

			Arrays.sort(A);
		}

		int su[]=new int[A.length];
		for(int i=0;i<su.length;i++){
			su[i]=A[i].index;
		}
		return su;
	}

}

//suffix array Struct
class Suffix implements Comparable<Suffix>{
	int index;
	int rank;
	int next;
	public Suffix(int i,int rank,int next){
		this.index=i;
		this.rank=rank;
		this.next=next;
	}

	@Override
	public int compareTo(Suffix other) {
		if(this.rank==other.rank){
			return this.next-other.next;
		}
		return this.rank-other.rank;
	}

	public String toString(){
		return this.index+"   "+this.rank+"   "+this.next+"  ";
	}
}

class Wrapper implements Comparable<Wrapper>{
	int spf;int cnt;
	public Wrapper(int spf,int cnt){
		this.spf=spf;
		this.cnt=cnt;
	}

	@Override
	public int compareTo(Wrapper other) {
		return this.spf-other.spf;
	}
}

    class Node{//what the range would be for that particular node
		boolean state=false;
        int l=0,r=0;
		int ll=0,rr=0;
        public Node(boolean state){
            this.state=state;
        }
    }

	class Seg1{
			int A[];
			public Seg1(int A[]){
				this.A=A;
			}

			public void update(int left,int right,int val,int s,int e,int id){
				if(left<0||right<0||left>right)return;
				if(left==s&&right==e){

					A[id]+=val;
					return;
				}
				int mid=s+(e-s)/2; //[s,mid] [mid+1,e]

				if(left>=mid+1){
					update(left,right,val,mid+1,e,id*2+2);
				}else if(right<=mid){
					update(left,right,val,s,mid,id*2+1);
				}else{
					update(left,mid,val,s,mid,id*2+1);
					update(mid+1,right,val,mid+1,e,id*2+2);
				}
			}

			public int query(int i,int add,int s,int e,int id){

				if(s==e&&i==s){
					return A[id]+add;
				}

				int mid=s+(e-s)/2; //[s,mid] [mid+1,e]

				if(i>=mid+1){
					return query(i,A[id]+add,mid+1,e,id*2+2);
				}else{
					return query(i,A[id]+add,s,mid,id*2+1);
				}
			}
	}

	 class MaxFlow{

		  public static List<Edge>[] createGraph(int nodes) {
			List<Edge>[] graph = new List[nodes];
			for (int i = 0; i < nodes; i++)
			  graph[i] = new ArrayList<>();
			return graph;
		  }

		  public static void addEdge(List<Edge>[] graph, int s, int t, int cap) {
			graph[s].add(new Edge(t, graph[t].size(), cap));
			graph[t].add(new Edge(s, graph[s].size() - 1, 0));
		  }

		  static boolean dinicBfs(List<Edge>[] graph, int src, int dest, int[] dist) {
			Arrays.fill(dist, -1);
			dist[src] = 0;
			int[] Q = new int[graph.length];
			int sizeQ = 0;
			Q[sizeQ++] = src;
			for (int i = 0; i < sizeQ; i++) {
			  int u = Q[i];
			  for (Edge e : graph[u]) {
				if (dist[e.t] < 0 && e.f < e.cap) {
				  dist[e.t] = dist[u] + 1;
				  Q[sizeQ++] = e.t;
				}
			  }
			}
			return dist[dest] >= 0;
		  }

		  static int dinicDfs(List<Edge>[] graph, int[] ptr, int[] dist, int dest, int u, int f) {
			if (u == dest)
			  return f;
			for (; ptr[u] < graph[u].size(); ++ptr[u]) {
			  Edge e = graph[u].get(ptr[u]);
			  if (dist[e.t] == dist[u] + 1 && e.f < e.cap) {
				int df = dinicDfs(graph, ptr, dist, dest, e.t, Math.min(f, e.cap - e.f));
				if (df > 0) {
				  e.f += df;
				  graph[e.t].get(e.rev).f -= df;
				  return df;
				}
			  }
			}
			return 0;
		  }

		  public static int maxFlow(List<Edge>[] graph, int src, int dest) {
			int flow = 0;
			int[] dist = new int[graph.length];
			while (dinicBfs(graph, src, dest, dist)) {
			  int[] ptr = new int[graph.length];
			  while (true) {
				int df = dinicDfs(graph, ptr, dist, dest, src, Integer.MAX_VALUE);
				if (df == 0)
				  break;
				flow += df;
			  }
			}
			return flow;
		  }

	 }

	 	 class Edge {
			int t, rev, cap, f;

			public Edge(int t, int rev, int cap) {
			  this.t = t;
			  this.rev = rev;
			  this.cap = cap;
			}
		  }

    class Seg{
        int l,r;
        int min=Integer.MAX_VALUE;
        Seg left=null,right=null;
		long sum=0;long cnt=0;
        public Seg(int l,int r){
            this.l=l;
            this.r=r;

        }
        public long[] query(int s,int e){
            if(l==s&&r==e){
                return new long[]{sum,cnt};
            }
            int mid=l+(r-l)/2; //left :  to mid-1,

			if(left==null)left=new Seg(l,mid);
			if(right==null)right=new Seg(mid+1,r);

			if(e<=mid){
                return left.query(s,e);
            }
            else if(s>=mid+1){
                return right.query(s,e);
            }else{
				long A[]=left.query(s,mid);
				long B[]=right.query(mid+1,e);
				return new long[]{A[0]+B[0],A[1]+B[1]};

            }
        }

        public void update(int index,int v){
			sum+=v;
			cnt++;
            if(l==r&&l==index){
                return;
            }
            int mid=l+(r-l)/2;
            if(index<=mid){
				if(left==null)left=new Seg(l,mid);
                left.update(index,v);
            }else{
				if(right==null)right=new Seg(mid+1,r);
                right.update(index,v);
            }

        }
    }


import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.Comparator;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.IOException;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.NoSuchElementException;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Egor Kulikov (egor@egork.net)
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		OutputWriter out = new OutputWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
	private static final long MOD = 1000000007;
	long[][][] answer;
	private int upTo;

	public void solve(int testNumber, InputReader in, OutputWriter out) {
		upTo = in.readInt();
		answer = new long[2][30][31];
		ArrayUtils.fill(answer, -1);
		long result = go(1, 29, 0);
		out.printLine(result);
    }

	private long go(int full, int bit, int groups) {
		if (groups < 0)
			return 0;
		if (bit == -1)
			return 1;
		if (answer[full][bit][groups] != -1)
			return answer[full][bit][groups];
		long result;
		if (full == 0 || (upTo >> bit & 1) == 1) {
			if (groups != 0)
				result = go(0, bit - 1, groups) * (1 << (groups - 1)) + go(full, bit - 1, groups) * (1 << (groups - 1)) + go(full, bit - 1, groups + 1);
			else
				result = go(full, bit - 1, 1) + go(0, bit - 1, groups);
		} else if ((upTo >> bit & 1) == 0 && groups != 0)
			result = go(full, bit - 1, groups) * (1 << (groups - 1));
		else
			result = go(full, bit - 1, groups);
		return answer[full][bit][groups] = result % MOD;
	}
}

class InputReader {

	private InputStream stream;
	private byte[] buf = new byte[1024];
	private int curChar;
	private int numChars;
	private SpaceCharFilter filter;

	public InputReader(InputStream stream) {
		this.stream = stream;
	}

	public int read() {
		if (numChars == -1)
			throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try {
				numChars = stream.read(buf);
			} catch (IOException e) {
				throw new InputMismatchException();
			}
			if (numChars <= 0)
				return -1;
		}
		return buf[curChar++];
	}

	public int readInt() {
		int c = read();
		while (isSpaceChar(c))
			c = read();
		int sgn = 1;
		if (c == '-') {
			sgn = -1;
			c = read();
		}
		int res = 0;
		do {
			if (c < '0' || c > '9')
				throw new InputMismatchException();
			res *= 10;
			res += c - '0';
			c = read();
		} while (!isSpaceChar(c));
		return res * sgn;
	}

	public boolean isSpaceChar(int c) {
		if (filter != null)
			return filter.isSpaceChar(c);
		return isWhitespace(c);
	}

	public static boolean isWhitespace(int c) {
		return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
	}

	public interface SpaceCharFilter {
		public boolean isSpaceChar(int ch);
	}
}

class OutputWriter {
	private final PrintWriter writer;

	public OutputWriter(OutputStream outputStream) {
		writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
	}

	public OutputWriter(Writer writer) {
		this.writer = new PrintWriter(writer);
	}

	public void close() {
		writer.close();
	}

	public void printLine(long i) {
		writer.println(i);
	}

	}

class ArrayUtils {

	public static void fill(long[][] array, long value) {
		for (long[] row : array)
			Arrays.fill(row, value);
	}

	public static void fill(long[][][] array, long value) {
		for (long[][] row : array)
			fill(row, value);
	}

	}


import java.io.*;
import java.util.*;

public class ETry implements Runnable {

    private PrintWriter out = new PrintWriter(System.out, true);
    private Scanner scanner;

    int n;
    int[] size;
    int[] parent;
    PointWI[] points;
    int[] ans;

    Graph graph;

    @Override
    public void run() {
        n = scanner.nextInt();
        // читаем граф
        graph = new Graph(n);

        for (int i = 0; i < n - 1; i++) {
            int x = scanner.nextInt() - 1;
            int y = scanner.nextInt() - 1;
            graph.addEdge(x, y);
        }

        // читаем точки
        points = new PointWI[n];
        for (int i = 0; i < n; i++) {
            points[i] = new PointWI(scanner.nextLong(), scanner.nextLong(), i);
        }

        // подвешиваем дерево и
        size = new int[n];
        parent = new int[n];
        dfs(0, -1);

        // считаем ответ
        ans = new int[n];
        Arrays.fill(ans, -1);

        // ищем самый левый
        int rootIndex = 0;
        for (int i = 1; i < n; i++) {
            if (points[i].x < points[rootIndex].x || points[i].x == points[rootIndex].x
                    && points[i].y < points[rootIndex].y) {
                rootIndex = i;
            }
        }

        // ставим самый левый первым
        PointWI tmp = points[0];
        points[0] = points[rootIndex];
        points[rootIndex] = tmp;

        // считаем
        rec(0, 0, n - 1);

        // ответ
        for (int i = 0; i < n; i++) {
            out.print(ans[i] + 1);
            if (i == n - 1) {
                out.println();
            } else {
                out.print(" ");
            }
        }
    }

    private void rec(int x, int left, int right) {
        ans[points[left].i] = x;
        Arrays.sort(points, left + 1, right + 1, new PointComparator(points[left]));
        int i = left + 1;
        for (int y : graph.adjacent(x)) {
            if (y != parent[x]) {
                rec(y, i, i + size[y] - 1);
                i += size[y];
            }
        }
    }

    private void dfs(int x, int p) {
        parent[x] = p;
        size[x] = 1;
        for (int y : graph.adjacent(x)) {
            if (y != p) {
                dfs(y, x);
                size[x] += size[y];
            }
        }
    }

    public ETry setInput(InputStream inputStream) {
        this.scanner = new Scanner(inputStream);
        return this;
    }

    public static void main(String[] args) {
        new ETry().setInput(System.in).run();
    }
}

class Graph {
    private final int n;
    private final List<List<Integer>> adj;

    public Graph(int n) {
        this.n = n;
        this.adj = new ArrayList<List<Integer>>(n);
        createAdjList(n);
    }

    private void createAdjList(int n) {
        while (n > 0) {
            this.adj.add(new ArrayList<Integer>());
            n--;
        }
    }

    public void addEdge(int v, int u) {
        adj.get(v).add(u);
        adj.get(u).add(v);
    }

    public Iterable<Integer> adjacent(int v) {
        return adj.get(v);
    }

    public int getN() {
        return n;
    }
}

//solution

class PointWI {
    long x, y;
    int i;

    public PointWI(long x, long y, int i) {
        this.x = x;
        this.y = y;
        this.i = i;
    }

    @Override
    public String toString() {
        return String.format("[(%d %d) %d]", x, y, i);
    }

}

class PointComparator implements Comparator<PointWI> {
    PointWI root;

    public PointComparator(PointWI root) {
        this.root = root;
    }

    @Override
    public int compare(PointWI a, PointWI b) {
        long wp = (a.x - root.x) * (b.y - root.y) - (a.y - root.y) * (b.x - root.x);
        if (wp < 0)
            return -1;
        if (wp > 0)
            return 1;
        return 0;
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            G2PlaylistForPolycarpHardVersion solver = new G2PlaylistForPolycarpHardVersion();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class G2PlaylistForPolycarpHardVersion {
        Modular mod = new Modular(1e9 + 7);

        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();
            int[][] musics = new int[n][2];
            int[] cnts = new int[4];
            for (int i = 0; i < n; i++) {
                musics[i][0] = in.readInt();
                musics[i][1] = in.readInt();
                cnts[musics[i][1]]++;
            }

            int c1 = cnts[1];
            int c2 = cnts[2];
            int c3 = cnts[3];

            int[][][][] comp = new int[c1 + 1][c2 + 1][c3 + 1][4];
            for (int i = 0; i <= c1; i++) {
                for (int j = 0; j <= c2; j++) {
                    for (int k = 0; k <= c3; k++) {
                        for (int t = 0; t < 4; t++) {
                            if (i == 0 && j == 0 && k == 0) {
                                comp[i][j][k][t] = 1;
                                continue;
                            }
                            if (i > 0 && t != 1) {
                                comp[i][j][k][t] = mod.plus(comp[i][j][k][t], mod.mul(comp[i - 1][j][k][1], i));
                            }
                            if (j > 0 && t != 2) {
                                comp[i][j][k][t] = mod.plus(comp[i][j][k][t], mod.mul(comp[i][j - 1][k][2], j));
                            }
                            if (k > 0 && t != 3) {
                                comp[i][j][k][t] = mod.plus(comp[i][j][k][t], mod.mul(comp[i][j][k - 1][3], k));
                            }
                        }
                    }
                }
            }

            int[][][][] last = new int[c1 + 1][c2 + 1][c3 + 1][m + 1];
            int[][][][] next = new int[c1 + 1][c2 + 1][c3 + 1][m + 1];

            last[0][0][0][0] = 1;
            int t1 = 0;
            int t2 = 0;
            int t3 = 0;
            for (int[] music : musics) {
                int m1 = music[1];
                int m0 = music[0];
                if (m1 == 1) {
                    t1++;
                } else if (m1 == 2) {
                    t2++;
                } else {
                    t3++;
                }
                for (int i = 0; i <= t1; i++) {
                    for (int j = 0; j <= t2; j++) {
                        for (int k = 0; k <= t3; k++) {
                            for (int t = 0; t <= m; t++) {
                                next[i][j][k][t] = last[i][j][k][t];
                                if (t < m0) {
                                    continue;
                                }
                                if (m1 == 1 && i > 0) {
                                    next[i][j][k][t] = mod.plus(next[i][j][k][t], last[i - 1][j][k][t - m0]);
                                } else if (m1 == 2 && j > 0) {
                                    next[i][j][k][t] = mod.plus(next[i][j][k][t], last[i][j - 1][k][t - m0]);
                                } else if (m1 == 3 && k > 0) {
                                    next[i][j][k][t] = mod.plus(next[i][j][k][t], last[i][j][k - 1][t - m0]);
                                }
                            }
                        }
                    }
                }

                int[][][][] tmp = last;
                last = next;
                next = tmp;
            }

            int ans = 0;
            for (int i = 0; i <= c1; i++) {
                for (int j = 0; j <= c2; j++) {
                    for (int k = 0; k <= c3; k++) {
                        ans = mod.plus(ans, mod.mul(last[i][j][k][m], comp[i][j][k][0]));
                    }
                }
            }

            out.println(ans);
        }

    }

    static class Modular {
        int m;

        public Modular(int m) {
            this.m = m;
        }

        public Modular(long m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public Modular(double m) {
            this.m = (int) m;
            if (this.m != m) {
                throw new IllegalArgumentException();
            }
        }

        public int valueOf(int x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return x;
        }

        public int valueOf(long x) {
            x %= m;
            if (x < 0) {
                x += m;
            }
            return (int) x;
        }

        public int mul(int x, int y) {
            return valueOf((long) x * y);
        }

        public int plus(int x, int y) {
            return valueOf(x + y);
        }

        public String toString() {
            return "mod " + m;
        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


import java.io.*;
import java.math.*;
import java.util.*;

public class Solution {
    final static int MOD = (int)1e9 + 7;

    public void run() {
        try {
            int n = reader.nextInt();
            int m = reader.nextInt();
            int[][] binom = new int[n + 1][n + 1];
            for (int i = 0; i <= n; ++ i) {
                binom[i][0] = 1;
                for (int j = 1; j <= i; ++ j) {
                    binom[i][j] = (binom[i - 1][j - 1] + binom[i - 1][j]) % MOD;
                }
            }
            int[][] ways = new int[n + 1][4];
            ways[0][1] = 1;
            for (int i = 0; i < n; ++ i) {
                int[][] newWays = new int[n + 1][4];
                for (int j = 0; j <= n; ++ j) {
                    for (int mask = 0; mask < 4; ++ mask) {
                        if (ways[j][mask] == 0) {
                            continue;
                        }
                        newWays[j][(mask << 1 | 1) & 3] += ways[j][mask];
                        newWays[j][(mask << 1 | 1) & 3] %= MOD;
                        if ((mask >> 1 & 1) == 1) {
                            newWays[j + 1][(mask << 1 | 1) & 3] += ways[j][mask];
                            newWays[j + 1][(mask << 1 | 1) & 3] %= MOD;
                        }
                        if (i + 1 < n) {
                            newWays[j + 1][mask << 1 & 3] += ways[j][mask];
                            newWays[j + 1][mask << 1 & 3] %= MOD;
                        }
                    }
                }
                ways = newWays;
            }
            int[] factorial = new int[n + 1];
            factorial[0] = 1;
            for (int i = 1; i <= n; ++ i) {
                factorial[i] = (int)((long)factorial[i - 1] * i % MOD);
            }
            int[] atLeast = new int[n + 1];
            for (int i = 0; i <= n; ++ i) {
                for (int mask = 0; mask < 4; ++ mask) {
                    atLeast[i] += (long)ways[i][mask] * factorial[n - i] % MOD;
                    atLeast[i] %= MOD;
                }
            }
            int[] exactly = new int[n + 1];
            for (int i = n; i >= 0; -- i) {
                exactly[i] = atLeast[i];
                for (int j = i + 1; j <= n; ++ j) {
                    exactly[i] -= (long)exactly[j] * binom[j][i] % MOD;
                    exactly[i] %= MOD;
                }
            }
            writer.println((exactly[m] + MOD) % MOD);
        } catch (IOException ex) {
        }
        writer.close();
    }

    InputReader reader;
    PrintWriter writer;

    Solution() {
        reader = new InputReader();
        writer = new PrintWriter(System.out);
    }

    public static void main(String[] args) {
        new Solution().run();
    }

    void debug(Object...os) {
        System.err.println(Arrays.deepToString(os));
    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

    InputReader() {
        reader = new BufferedReader(new InputStreamReader(System.in));
        tokenizer = new StringTokenizer("");
    }

    String next() throws IOException {
        while (!tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    Integer nextInt() throws IOException {
        return Integer.parseInt(next());
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.util.InputMismatchException;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author svilen.marchev@gmail.com
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    InputReader in = new InputReader(inputStream);
    PrintWriter out = new PrintWriter(outputStream);
    TaskF solver = new TaskF();
    solver.solve(1, in, out);
    out.close();
  }

  static class TaskF {
    int n;
    char[] s;
    int[] ugliness;

    public void solve(int testNumber, InputReader in, PrintWriter out) {
      n = in.readInt();
      s = in.readString().toCharArray();
      ugliness = new int[n];
      for (int i = 0; i < n; ++i) {
        ugliness[i] = -in.readInt();
      }

      Graph graph = new Graph(1 + 26 + n / 2 + 1);
      for (char c = 'a'; c <= 'z'; ++c) {
        for (int i = 0; i < n / 2; ++i) {
          int cost = 0;
          if (c == s[i]) {
            cost = Math.min(cost, ugliness[i]);
          }
          if (c == s[n - 1 - i]) {
            cost = Math.min(cost, ugliness[n - 1 - i]);
          }
          graph.addFlowWeightedEdge(1 + (c - 'a'), 1 + 26 + i, cost, 1);
        }
      }

      int[] occurs = new int[128];
      for (int i = 0; i < n; ++i) occurs[s[i]]++;
      for (char c = 'a'; c <= 'z'; ++c) {
        graph.addFlowWeightedEdge(0, 1 + (c - 'a'), 0, occurs[c]);
      }

      for (int i = 0; i < n / 2; ++i) {
        graph.addFlowWeightedEdge(1 + 26 + i, 1 + 26 + n / 2, 0, 2);
      }

      Pair<Long, Long> flow = MinCostFlow.minCostMaxFlow(graph, 0, 1 + 26 + n / 2, true, n);
      out.println(-flow.first);
    }

  }

  static class Pair<U, V> implements Comparable<Pair<U, V>> {
    public final U first;
    public final V second;

    public static <U, V> Pair<U, V> makePair(U first, V second) {
      return new Pair<U, V>(first, second);
    }

    private Pair(U first, V second) {
      this.first = first;
      this.second = second;
    }

    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }

      Pair pair = (Pair) o;

      return !(first != null ? !first.equals(pair.first) : pair.first != null) &&
          !(second != null ? !second.equals(pair.second) : pair.second != null);
    }

    public int hashCode() {
      int result = first != null ? first.hashCode() : 0;
      result = 31 * result + (second != null ? second.hashCode() : 0);
      return result;
    }

    public String toString() {
      return "(" + first + "," + second + ")";
    }

    @SuppressWarnings({"unchecked"})
    public int compareTo(Pair<U, V> o) {
      int value = ((Comparable<U>) first).compareTo(o.first);
      if (value != 0) {
        return value;
      }
      return ((Comparable<V>) second).compareTo(o.second);
    }

  }

  static class IntegerUtils {
    public static int longCompare(long a, long b) {
      if (a < b) {
        return -1;
      }
      if (a > b) {
        return 1;
      }
      return 0;
    }

  }

  static interface IntStream extends Iterable<Integer>, Comparable<IntStream> {
    public IntIterator intIterator();

    default public Iterator<Integer> iterator() {
      return new Iterator<Integer>() {
        private IntIterator it = intIterator();

        public boolean hasNext() {
          return it.isValid();
        }

        public Integer next() {
          int result = it.value();
          it.advance();
          return result;
        }
      };
    }

    default public int compareTo(IntStream c) {
      IntIterator it = intIterator();
      IntIterator jt = c.intIterator();
      while (it.isValid() && jt.isValid()) {
        int i = it.value();
        int j = jt.value();
        if (i < j) {
          return -1;
        } else if (i > j) {
          return 1;
        }
        it.advance();
        jt.advance();
      }
      if (it.isValid()) {
        return 1;
      }
      if (jt.isValid()) {
        return -1;
      }
      return 0;
    }

  }

  static class Heap implements IntQueue {
    private IntComparator comparator;
    private int size = 0;
    private int[] elements;
    private int[] at;

    public Heap(int maxElement) {
      this(10, maxElement);
    }

    public Heap(IntComparator comparator, int maxElement) {
      this(10, comparator, maxElement);
    }

    public Heap(int capacity, int maxElement) {
      this(capacity, IntComparator.DEFAULT, maxElement);
    }

    public Heap(int capacity, IntComparator comparator, int maxElement) {
      this.comparator = comparator;
      elements = new int[capacity];
      at = new int[maxElement];
      Arrays.fill(at, -1);
    }

    public boolean isEmpty() {
      return size == 0;
    }

    public void add(int element) {
      ensureCapacity(size + 1);
      elements[size] = element;
      at[element] = size;
      shiftUp(size++);
    }

    public void shiftUp(int index) {
      //		if (index < 0 || index >= size)
      //			throw new IllegalArgumentException();
      int value = elements[index];
      while (index != 0) {
        int parent = (index - 1) >>> 1;
        int parentValue = elements[parent];
        if (comparator.compare(parentValue, value) <= 0) {
          elements[index] = value;
          at[value] = index;
          return;
        }
        elements[index] = parentValue;
        at[parentValue] = index;
        index = parent;
      }
      elements[0] = value;
      at[value] = 0;
    }

    public void shiftDown(int index) {
      if (index < 0 || index >= size) {
        throw new IllegalArgumentException();
      }
      while (true) {
        int child = (index << 1) + 1;
        if (child >= size) {
          return;
        }
        if (child + 1 < size && comparator.compare(elements[child], elements[child + 1]) > 0) {
          child++;
        }
        if (comparator.compare(elements[index], elements[child]) <= 0) {
          return;
        }
        swap(index, child);
        index = child;
      }
    }

    public int getIndex(int element) {
      return at[element];
    }

    private void swap(int first, int second) {
      int temp = elements[first];
      elements[first] = elements[second];
      elements[second] = temp;
      at[elements[first]] = first;
      at[elements[second]] = second;
    }

    private void ensureCapacity(int size) {
      if (elements.length < size) {
        int[] oldElements = elements;
        elements = new int[Math.max(2 * elements.length, size)];
        System.arraycopy(oldElements, 0, elements, 0, this.size);
      }
    }

    public int poll() {
      if (isEmpty()) {
        throw new IndexOutOfBoundsException();
      }
      int result = elements[0];
      at[result] = -1;
      if (size == 1) {
        size = 0;
        return result;
      }
      elements[0] = elements[--size];
      at[elements[0]] = 0;
      shiftDown(0);
      return result;
    }

    public IntIterator intIterator() {
      return new IntIterator() {
        private int at;

        public int value() throws NoSuchElementException {
          return elements[at];
        }

        public boolean advance() throws NoSuchElementException {
          return ++at < size;
        }

        public boolean isValid() {
          return at < size;
        }

        public void remove() throws NoSuchElementException {
          throw new UnsupportedOperationException();
        }
      };
    }

  }

  static class InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private InputReader.SpaceCharFilter filter;

    public InputReader(InputStream stream) {
      this.stream = stream;
    }

    public int read() {
      if (numChars == -1) {
        throw new InputMismatchException();
      }
      if (curChar >= numChars) {
        curChar = 0;
        try {
          numChars = stream.read(buf);
        } catch (IOException e) {
          throw new InputMismatchException();
        }
        if (numChars <= 0) {
          return -1;
        }
      }
      return buf[curChar++];
    }

    public int readInt() {
      int c = read();
      while (isSpaceChar(c)) {
        c = read();
      }
      int sgn = 1;
      if (c == '-') {
        sgn = -1;
        c = read();
      }
      int res = 0;
      do {
        if (c < '0' || c > '9') {
          throw new InputMismatchException();
        }
        res *= 10;
        res += c - '0';
        c = read();
      } while (!isSpaceChar(c));
      return res * sgn;
    }

    public String readString() {
      int c = read();
      while (isSpaceChar(c)) {
        c = read();
      }
      StringBuilder res = new StringBuilder();
      do {
        if (Character.isValidCodePoint(c)) {
          res.appendCodePoint(c);
        }
        c = read();
      } while (!isSpaceChar(c));
      return res.toString();
    }

    public boolean isSpaceChar(int c) {
      if (filter != null) {
        return filter.isSpaceChar(c);
      }
      return isWhitespace(c);
    }

    public static boolean isWhitespace(int c) {
      return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
      public boolean isSpaceChar(int ch);

    }

  }

  static interface IntComparator {
    public static final IntComparator DEFAULT = (first, second) -> {
      if (first < second) {
        return -1;
      }
      if (first > second) {
        return 1;
      }
      return 0;
    };

    public int compare(int first, int second);

  }

  static interface IntIterator {
    public int value() throws NoSuchElementException;

    public boolean advance();

    public boolean isValid();

  }

  static interface IntQueue extends IntCollection {
  }

  static interface Edge {
  }

  static class Graph {
    public static final int REMOVED_BIT = 0;
    protected int vertexCount;
    protected int edgeCount;
    private int[] firstOutbound;
    private int[] firstInbound;
    private Edge[] edges;
    private int[] nextInbound;
    private int[] nextOutbound;
    private int[] from;
    private int[] to;
    private long[] weight;
    public long[] capacity;
    private int[] reverseEdge;
    private int[] flags;

    public Graph(int vertexCount) {
      this(vertexCount, vertexCount);
    }

    public Graph(int vertexCount, int edgeCapacity) {
      this.vertexCount = vertexCount;
      firstOutbound = new int[vertexCount];
      Arrays.fill(firstOutbound, -1);

      from = new int[edgeCapacity];
      to = new int[edgeCapacity];
      nextOutbound = new int[edgeCapacity];
      flags = new int[edgeCapacity];
    }

    public int addEdge(int fromID, int toID, long weight, long capacity, int reverseEdge) {
      ensureEdgeCapacity(edgeCount + 1);
      if (firstOutbound[fromID] != -1) {
        nextOutbound[edgeCount] = firstOutbound[fromID];
      } else {
        nextOutbound[edgeCount] = -1;
      }
      firstOutbound[fromID] = edgeCount;
      if (firstInbound != null) {
        if (firstInbound[toID] != -1) {
          nextInbound[edgeCount] = firstInbound[toID];
        } else {
          nextInbound[edgeCount] = -1;
        }
        firstInbound[toID] = edgeCount;
      }
      this.from[edgeCount] = fromID;
      this.to[edgeCount] = toID;
      if (capacity != 0) {
        if (this.capacity == null) {
          this.capacity = new long[from.length];
        }
        this.capacity[edgeCount] = capacity;
      }
      if (weight != 0) {
        if (this.weight == null) {
          this.weight = new long[from.length];
        }
        this.weight[edgeCount] = weight;
      }
      if (reverseEdge != -1) {
        if (this.reverseEdge == null) {
          this.reverseEdge = new int[from.length];
          Arrays.fill(this.reverseEdge, 0, edgeCount, -1);
        }
        this.reverseEdge[edgeCount] = reverseEdge;
      }
      if (edges != null) {
        edges[edgeCount] = createEdge(edgeCount);
      }
      return edgeCount++;
    }

    protected final GraphEdge createEdge(int id) {
      return new GraphEdge(id);
    }

    public final int addFlowWeightedEdge(int from, int to, long weight, long capacity) {
      if (capacity == 0) {
        return addEdge(from, to, weight, 0, -1);
      } else {
        int lastEdgeCount = edgeCount;
        addEdge(to, from, -weight, 0, lastEdgeCount + entriesPerEdge());
        return addEdge(from, to, weight, capacity, lastEdgeCount);
      }
    }

    protected int entriesPerEdge() {
      return 1;
    }

    public final int vertexCount() {
      return vertexCount;
    }

    public final int firstOutbound(int vertex) {
      int id = firstOutbound[vertex];
      while (id != -1 && isRemoved(id)) {
        id = nextOutbound[id];
      }
      return id;
    }

    public final int nextOutbound(int id) {
      id = nextOutbound[id];
      while (id != -1 && isRemoved(id)) {
        id = nextOutbound[id];
      }
      return id;
    }

    public final int source(int id) {
      return from[id];
    }

    public final int destination(int id) {
      return to[id];
    }

    public final long weight(int id) {
      if (weight == null) {
        return 0;
      }
      return weight[id];
    }

    public final long capacity(int id) {
      if (capacity == null) {
        return 0;
      }
      return capacity[id];
    }

    public final long flow(int id) {
      if (reverseEdge == null) {
        return 0;
      }
      return capacity[reverseEdge[id]];
    }

    public final void pushFlow(int id, long flow) {
      if (flow == 0) {
        return;
      }
      if (flow > 0) {
        if (capacity(id) < flow) {
          throw new IllegalArgumentException("Not enough capacity");
        }
      } else {
        if (flow(id) < -flow) {
          throw new IllegalArgumentException("Not enough capacity");
        }
      }
      capacity[id] -= flow;
      capacity[reverseEdge[id]] += flow;
    }

    public final boolean flag(int id, int bit) {
      return (flags[id] >> bit & 1) != 0;
    }

    public final boolean isRemoved(int id) {
      return flag(id, REMOVED_BIT);
    }

    protected void ensureEdgeCapacity(int size) {
      if (from.length < size) {
        int newSize = Math.max(size, 2 * from.length);
        if (edges != null) {
          edges = resize(edges, newSize);
        }
        from = resize(from, newSize);
        to = resize(to, newSize);
        nextOutbound = resize(nextOutbound, newSize);
        if (nextInbound != null) {
          nextInbound = resize(nextInbound, newSize);
        }
        if (weight != null) {
          weight = resize(weight, newSize);
        }
        if (capacity != null) {
          capacity = resize(capacity, newSize);
        }
        if (reverseEdge != null) {
          reverseEdge = resize(reverseEdge, newSize);
        }
        flags = resize(flags, newSize);
      }
    }

    protected final int[] resize(int[] array, int size) {
      int[] newArray = new int[size];
      System.arraycopy(array, 0, newArray, 0, array.length);
      return newArray;
    }

    private long[] resize(long[] array, int size) {
      long[] newArray = new long[size];
      System.arraycopy(array, 0, newArray, 0, array.length);
      return newArray;
    }

    private Edge[] resize(Edge[] array, int size) {
      Edge[] newArray = new Edge[size];
      System.arraycopy(array, 0, newArray, 0, array.length);
      return newArray;
    }

    public final boolean isSparse() {
      return vertexCount == 0 || edgeCount * 20 / vertexCount <= vertexCount;
    }

    protected class GraphEdge implements Edge {
      protected int id;

      protected GraphEdge(int id) {
        this.id = id;
      }

    }

  }

  static class MinCostFlow {
    private final Graph graph;
    private final int source;
    private final int destination;
    private final long[] phi;
    private final long[] dijkstraResult;
    private final int[] lastEdge;
    private final Heap heap;
    private final int vertexCount;
    private final int[] visited;
    private int visitIndex;

    public MinCostFlow(Graph graph, int source, int destination, boolean hasNegativeEdges) {
      this.graph = graph;
      this.source = source;
      this.destination = destination;
      vertexCount = graph.vertexCount();
      phi = new long[vertexCount];
      if (hasNegativeEdges) {
        fordBellman();
      }
      dijkstraResult = new long[vertexCount];
      lastEdge = new int[vertexCount];
      if (graph.isSparse()) {
        heap = new Heap(vertexCount, new IntComparator() {
          public int compare(int first, int second) {
            return IntegerUtils.longCompare(dijkstraResult[first], dijkstraResult[second]);
          }
        }, vertexCount);
        visited = null;
      } else {
        heap = null;
        visited = new int[vertexCount];
      }
    }

    private void fordBellman() {
      Arrays.fill(phi, Long.MAX_VALUE);
      phi[source] = 0;
      boolean[] inQueue = new boolean[vertexCount];
      int[] queue = new int[vertexCount + 1];
      queue[0] = source;
      inQueue[source] = true;
      int stepCount = 0;
      int head = 0;
      int end = 1;
      int maxSteps = 2 * vertexCount * vertexCount;
      while (head != end) {
        int vertex = queue[head++];
        if (head == queue.length) {
          head = 0;
        }
        inQueue[vertex] = false;
        int edgeID = graph.firstOutbound(vertex);
        while (edgeID != -1) {
          long total = phi[vertex] + graph.weight(edgeID);
          int destination = graph.destination(edgeID);
          if (graph.capacity(edgeID) != 0 && phi[destination] > total) {
            phi[destination] = total;
            if (!inQueue[destination]) {
              queue[end++] = destination;
              inQueue[destination] = true;
              if (end == queue.length) {
                end = 0;
              }
            }
          }
          edgeID = graph.nextOutbound(edgeID);
        }
        if (++stepCount > maxSteps) {
          throw new IllegalArgumentException("Graph contains negative cycle");
        }
      }
    }

    public static Pair<Long, Long> minCostMaxFlow(Graph graph, int source, int destination, boolean hasNegativeEdges,
                                                  long maxFlow) {
      return new MinCostFlow(graph, source, destination, hasNegativeEdges).minCostMaxFlow(maxFlow);
    }

    public Pair<Long, Long> minCostMaxFlow(long maxFlow) {
      long cost = 0;
      long flow = 0;
      while (maxFlow != 0) {
        if (graph.isSparse()) {
          dijkstraAlgorithm();
        } else {
          dijkstraAlgorithmFull();
        }
        if (lastEdge[destination] == -1) {
          return Pair.makePair(cost, flow);
        }
        for (int i = 0; i < dijkstraResult.length; i++) {
          if (dijkstraResult[i] != Long.MAX_VALUE) {
            phi[i] += dijkstraResult[i];
          }
        }
        int vertex = destination;
        long currentFlow = maxFlow;
        long currentCost = 0;
        while (vertex != source) {
          int edgeID = lastEdge[vertex];
          currentFlow = Math.min(currentFlow, graph.capacity(edgeID));
          currentCost += graph.weight(edgeID);
          vertex = graph.source(edgeID);
        }
        maxFlow -= currentFlow;
        cost += currentCost * currentFlow;
        flow += currentFlow;
        vertex = destination;
        while (vertex != source) {
          int edgeID = lastEdge[vertex];
          graph.pushFlow(edgeID, currentFlow);
          vertex = graph.source(edgeID);
        }
      }
      return Pair.makePair(cost, flow);
    }

    private void dijkstraAlgorithm() {
      Arrays.fill(dijkstraResult, Long.MAX_VALUE);
      Arrays.fill(lastEdge, -1);
      dijkstraResult[source] = 0;
      heap.add(source);
      while (!heap.isEmpty()) {
        int current = heap.poll();
        int edgeID = graph.firstOutbound(current);
        while (edgeID != -1) {
          if (graph.capacity(edgeID) != 0) {
            int next = graph.destination(edgeID);
            long total = graph.weight(edgeID) - phi[next] + phi[current] + dijkstraResult[current];
            if (dijkstraResult[next] > total) {
              dijkstraResult[next] = total;
              if (heap.getIndex(next) == -1) {
                heap.add(next);
              } else {
                heap.shiftUp(heap.getIndex(next));
              }
              lastEdge[next] = edgeID;
            }
          }
          edgeID = graph.nextOutbound(edgeID);
        }
      }
    }

    private void dijkstraAlgorithmFull() {
      visitIndex++;
      Arrays.fill(dijkstraResult, Long.MAX_VALUE);
      lastEdge[destination] = -1;
      dijkstraResult[source] = 0;
      for (int i = 0; i < vertexCount; i++) {
        int index = -1;
        long length = Long.MAX_VALUE;
        for (int j = 0; j < vertexCount; j++) {
          if (visited[j] != visitIndex && dijkstraResult[j] < length) {
            length = dijkstraResult[j];
            index = j;
          }
        }
        if (index == -1) {
          return;
        }
        visited[index] = visitIndex;
        int edgeID = graph.firstOutbound(index);
        while (edgeID != -1) {
          if (graph.capacity(edgeID) != 0) {
            int next = graph.destination(edgeID);
            if (visited[next] != visitIndex) {
              long total = graph.weight(edgeID) - phi[next] + phi[index] + length;
              if (dijkstraResult[next] > total) {
                dijkstraResult[next] = total;
                lastEdge[next] = edgeID;
              }
            }
          }
          edgeID = graph.nextOutbound(edgeID);
        }
      }
    }

  }

  static interface IntCollection extends IntStream {
  }
}


import java.util.Scanner;
import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskD {
    long MOD = (long)1e9 + 7;
    long p[];

    public void solve(int testNumber, Scanner in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();
        int g = in.nextInt();
        p = new long[m + n + 1];
        p[0] = 1;
        for(int i = 1; i < p.length; ++i) p[i] = p[i - 1] * i % MOD;

        long res = 0;
        if(g == 1)
            res = rec(n, m);
        else if(g == 0) {
            if(n == 0 && m == 0)
                res = 0;
            else if(n == 1 && m == 0)
                res = 1;
            else if(n == 0 && m == 1)
                res = 0;
            else {
                if(n >= 1)
                    res = (res + rec(n - 1, m)) % MOD;
                if(m >= 1)
                    res = (res + p[n + m - 1] * modPow(p[n] * p[m - 1] % MOD, MOD - 2) % MOD) % MOD;
            }
        }
        out.println(res);
    }

    private long rec(int n, int m) {
        long res = 0;
        for(int i = n; i >= 0; ) {
            if(i == 1) {
                if(m <= 1) return res;
                else if(m > 1) {res = (res + 1) % MOD; return res;}
            }
            else if(i == 0) {
                if(m == 0 || m > 1) return res;
                else if(m == 1) {res = (res + 1) % MOD; return res;}
            }
            else if(i == 2 && m == 0) {res = (res + 1) % MOD; return res;}
            else if(i == 0 && m == 2) return res;

            else {
                if(i > 1 && m >= 1)
                    res = (res + p[m - 1 + i - 1] * modPow(p[m - 1] * p[i - 1] % MOD, MOD - 2) % MOD) % MOD;
                i -= 2;
            }
        }
        return res;
    }

    private long modPow(long a, long p) {
        if(p == 0) return 1;
        long res = modPow(a, p / 2);
        res = res * res % MOD;
        if(p % 2 == 1)
            res = res * a % MOD;
        return res;
    }
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class B138 {

    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int[]d1 = new int[10], d2 = new int[10];
        while (true) {
            int w = (int)br.read();
            if (w==13)
                break;
            d1[w-48]++;
            d2[w-48]++;
        }
        int[][]ten = {{2,8}, {3,7}, {4,6}, {5,5}, {1,9}};
        int[][]nine = {{1,8}, {2,7}, {3,6}, {4,5}, {5,4}, {6,3}, {7,2}, {8,1}, {0,9}, {9,0}};
        int[]zero = new int[5];
        int max = 0, k = -1;
        for (int t = 0; t < 5; t++) {
            if (d1[ten[t][0]] > 0 && d2[ten[t][1]] > 0) {
                zero[t] = 1;
                d1[ten[t][0]]--;
                d2[ten[t][1]]--;
                int[]min = new int[10];
                for (int i = 0; i < 10; i++) {
                    min[i] = Math.min(d1[nine[i][0]], d2[nine[i][1]]);
                    zero[t] += min[i];
                    d1[nine[i][0]] -= min[i];
                    d2[nine[i][1]] -= min[i];
                }
                zero[t] += Math.min(d1[0], d2[0]);
                if (zero[t] > max){
                    max = zero[t];
                    k = t;
                }
                for (int i = 0; i < 10; i++) {
                    d1[nine[i][0]] += min[i];
                    d2[nine[i][1]] += min[i];
                }
                d1[ten[t][0]]++;
                d2[ten[t][1]]++;
            }
        }
        if (k==-1) {
            for (int i = 1; i <= 9; i++) {
                for (int j = 1; j <= d1[i]; j++) {
                    pw.print(i);
                }
            }
            for (int i = 1; i <= d1[0] ; i++) {
                pw.print(0);
            }
            pw.println();
            for (int i = 1; i <= 9; i++) {
                for (int j = 1; j <= d1[i]; j++) {
                    pw.print(i);
                }
            }
            for (int i = 1; i <= d1[0] ; i++) {
                pw.print(0);
            }
        }
        else {
            int[]min = new int[10];
            d1[ten[k][0]]--;
            d2[ten[k][1]]--;
            for (int i = 0; i < 10; i++) {
                min[i] = Math.min(d1[nine[i][0]], d2[nine[i][1]]);
                d1[nine[i][0]] -= min[i];
                d2[nine[i][1]] -= min[i];
            }
            for (int i = 1; i <= 9; i++) {
                for (int j = 1; j <= d1[i]; j++) {
                    pw.print(i);
                }
            }
            int m = Math.min(d1[0], d2[0]);
            for (int i = 1; i <= d1[0]-d2[0]; i++) {
                pw.print(0);
            }
            for (int i = 0; i < 10; i++) {
                for (int j = 1; j <= min[i]; j++) {
                    pw.print(nine[i][0]);
                }
            }
            pw.print(ten[k][0]);
            for (int i = 1; i <= m; i++) {
                pw.print(0);
            }
            pw.println();
            for (int i = 1; i <= 9; i++) {
                for (int j = 1; j <= d2[i]; j++) {
                    pw.print(i);
                }
            }
            for (int i = 1; i <= d2[0]-d1[0]; i++) {
                pw.print(0);
            }
            for (int i = 0; i < 10; i++) {
                for (int j = 1; j <= min[i]; j++) {
                    pw.print(nine[i][1]);
                }
            }
            pw.print(ten[k][1]);
            for (int i = 1; i <= m; i++) {
                pw.print(0);
            }
        }
        pw.close();
    }
}


import java.io.*;
import java.util.*;

public class Codeforces913F {
	public static void main(String[] args) throws IOException {
		Scanner input = new Scanner(System.in);
		int n = input.nextInt();
		int a = input.nextInt();
		int b = input.nextInt();
		input.close();
		final int mod = 998244353;

		int frac = multiply(a, inverse(b, mod), mod);
		int reverse = (mod+1-frac)%mod;

		int[] fracpower = new int[n+1];
		int[] reversepower = new int[n+1];
		fracpower[0] = 1;
		reversepower[0] = 1;
		for (int i = 1; i <= n; i++) {
			fracpower[i] = multiply(fracpower[i-1], frac, mod);
			reversepower[i] = multiply(reversepower[i-1], reverse, mod);
		}

		int[][] dp1 = new int[n+1][n+1];
		dp1[2][1] = 1;
		for (int i = 3; i <= n; i++) {
			for (int j = 1; j < i; j++) {
				if (j == 1) {
					dp1[i][j] = fracpower[i-1];
				}
				else {
					dp1[i][j] = multiply(dp1[i-1][j-1], fracpower[i-j], mod);
				}
				if (j == i-1) {
					dp1[i][j] += reversepower[i-1];
					dp1[i][j] %= mod;
				}
				else {
					dp1[i][j] += multiply(dp1[i-1][j], reversepower[j], mod);
					dp1[i][j] %= mod;
				}
			}
		}

		int[][] dp2 = new int[n+1][n+1];
		dp2[1][1] = 1;
		dp2[2][1] = 1;
		dp2[2][2] = 0;
		for (int i = 3; i <= n; i++) {
			int val = 0;
			for (int j = 1; j < i; j++) {
				dp2[i][j] = multiply(dp2[j][j], dp1[i][j], mod);
				val += dp2[i][j];
				val %= mod;
			}
			dp2[i][i] = (mod+1-val)%mod;
		}

		/*for (int i = 2; i <= n; i++) {
			for (int j = 1; j <= i; j++) {
				System.out.print(dp2[i][j] + " ");
			}
			System.out.println();
		}*/

		int[] EV = new int[n+1];
		EV[1] = 0;
		EV[2] = 1;
		for (int i = 3; i <= n; i++) {
			int val = 0;
			for (int j = 1; j < i; j++) {
				int r = j*(i-j) + (j*(j-1))/2 + EV[i-j] + EV[j];
				r %= mod;
				val += multiply(dp2[i][j], r, mod);
				val %= mod;
			}
			val += multiply((i*(i-1))/2, dp2[i][i], mod);
			val %= mod;

			int s = (mod+1-dp2[i][i])%mod;
			EV[i] = multiply(val, inverse(s, mod), mod);
		}

		System.out.println(EV[n]);
	}

	public static int multiply(int a, int b, int mod) {
		long x = (long)a*(long)b;
		return (int) (x%mod);
	}

	public static int inverse (int a, int n) {
		int m = n;
		int r1 = 1;
		int r2 = 0;
		int r3 = 0;
		int r4 = 1;
		while ((a > 0) && (n > 0)) {
			if (n >= a) {
				r3 -= r1*(n/a);
				r4 -= r2*(n/a);
				n = n%a;
			}
			else {
				int tmp = a;
				a = n;
				n = tmp;
				tmp = r1;
				r1 = r3;
				r3 = tmp;
				tmp = r2;
				r2 = r4;
				r4 = tmp;
			}
		}
		if (a == 0) {
			if (r3 >= 0)
				return (r3%m);
			else
				return (m+(r3%m));
		}
		else {
			if (r1 >= 0)
				return (r1%m);
			else
				return (m+(r1%m));
		}

	}
}


import java.io.*;
import java.util.*;

public class cf286c {
  public static void main(String[] args) {
    FastIO in = new FastIO(), out = in;
    int n = in.nextInt();
    if(n%2 == 1) {
      out.println("NO");
      out.close();
      return;
    }
    int[] v = new int[n];
    for(int i=0; i<n; i++) v[i] = in.nextInt();
    int m = in.nextInt();
    for(int i=0; i<m; i++)
      v[in.nextInt()-1] *= -1;
    Stack<Pair<Integer,Integer>> stk1 = new Stack<>();
    Stack<Pair<Integer,Integer>> stk2 = new Stack<>();
    boolean fail = false;
    for(int i=0; i<n; i++) {
      if(v[i] > 0) stk1.add(new Pair<Integer,Integer>(v[i],i));
      else stk2.add(new Pair<Integer,Integer>(v[i],i));
      while(stk2.size() != 0 || (i==n-1 && stk1.size() != 0)) {
        if(stk1.size() == 0) {
          fail = true;
          break;
        }
        if(stk2.size() > 0 && stk1.peek().first == -stk2.peek().first) {
          stk1.pop();
          stk2.pop();
        }
        else {
          Pair<Integer,Integer> p = stk1.pop();
          p.first *= -1;
          v[p.second] = p.first;
          stk2.push(p);
        }
      }
    }
    if(fail) out.println("NO");
    else {
      out.println("YES");
      for(int x : v) out.print(x+ " ");
    }
    out.close();
  }
  static class Pair<T1,T2> {
    T1 first;
    T2 second;
    Pair(T1 a, T2 b) {
      first = a; second = b;
    }
    public String toString() {
      return first + ":" + second;
    }
  }

  static class FastIO extends PrintWriter {
    BufferedReader br;
    StringTokenizer st;

    public FastIO() {
      this(System.in, System.out);
    }

    public FastIO(InputStream in, OutputStream out) {
      super(new BufferedWriter(new OutputStreamWriter(out)));
      br = new BufferedReader(new InputStreamReader(in));
      scanLine();
    }

    public void scanLine() {
      try {
        st = new StringTokenizer(br.readLine().trim());
      } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
      }
    }

    public int numTokens() {
      if (!st.hasMoreTokens()) {
        scanLine();
        return numTokens();
      }
      return st.countTokens();
    }

    public String next() {
      if (!st.hasMoreTokens()) {
        scanLine();
        return next();
      }
      return st.nextToken();
    }

    public double nextDouble() {
      return Double.parseDouble(next());
    }

    public long nextLong() {
      return Long.parseLong(next());
    }

    public int nextInt() {
      return Integer.parseInt(next());
    }
  }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

/**
 * @author Pavel Mavrin
 */
public class E {

    private static final int MOD = (int) (1e9+7);
    public static final int N = 7;
    public static final int NN = 128;

    private void solve() throws IOException {
        int[] w = new int[N];
        for (int i = 0; i < N; i++) {
            w[i] = nextInt();
        }
        int[] start = new int[2];
        start[1] = 1;
        int[] a = start;
        for (int h = 0; h < N; h++) if (w[h] > 0) {
            int nn = (1 << (h + 1));
            {
                int[] aa = new int[nn];
                for (int i = 0; i < a.length; i++) {
                    aa[i - a.length + nn] = a[i];
                }
                a = aa;
            }
            int[][] q = new int[nn][];
            int[] t = new int[nn];
            for (int i = 0; i < nn; i++) {
                t[i] = 1;
                q[i] = add(t, h + 1);
                t[i] = 0;
            }
            q = pow(q, w[h]);
            int[] aa = new int[nn];
            for (int i = 0; i < nn; i++) {
                for (int j = 0; j < nn; j++) {
                    aa[j] = (int) ((aa[j] + 1l * a[i] * q[i][j]) % MOD);
                }
            }
            a = aa;
        }
        out.println(a[a.length - 1]);
    }

    private int[][] pow(int[][] a, int b) {
        int n = a.length;
        if (b == 0) {
            int[][] res = new int[n][n];
            for (int i = 0; i < n; i++) {
                res[i][i] = 1;
            }
            return res;
        }
        if (b % 2 == 0) {
            int[][] aa = mult(a, a);
            return pow(aa, b / 2);
        } else {
            int[][] aa = pow(a, b - 1);
            return mult(aa, a);
        }
    }

    private int[][] mult(int[][] a, int[][] b) {
        int n = a.length;
        int[][] c = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    c[i][k] = (int) ((c[i][k] + 1l * a[i][j] * b[j][k]) % MOD);
                }
            }
        }
        return c;
    }

    private int[] add(int[] a, int n) {
        int nn = (1 << (n + 1));
        int[][] d = new int[n + 1][nn];
        for (int i = 0; i < nn / 2; i++) {
            d[0][(i << 1) + 1] = a[i + a.length - (1 << n)];
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < nn; j++) if (d[i][j] > 0) {
                int q = (j >> i) & 3;
                for (int k = 0; k < 4; k++) {
                    if (q == 3 && k == 3) continue;
                    int jj = (j - (q << i) + (k << i));
                    d[i + 1][jj] += d[i][j];
                    while (d[i + 1][jj] >= MOD) {
                        d[i + 1][jj] -= MOD;
                    }
                }
            }
        }
        int[] res = new int[a.length];
        for (int i = 0; i < (1 << n); i++) {
            res[i + a.length - (1 << n)] = d[n][i + (1 << n)];
        }
        return res;
    }

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st;
    PrintWriter out = new PrintWriter(System.out);

    String next() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(br.readLine());
        }
        return st.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    public static void main(String[] args) throws IOException {
        new E().run();
    }

    private void run() throws IOException {
        solve();
        out.close();
    }

}