import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Arrays; import java.util.Scanner; public class Main { static InputStream is; static PrintWriter out; static String INPUT = ""; public static void main(String[] args) throws Exception { is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes()); out = new PrintWriter(System.out); solver(); out.flush(); } static long nl() { try { long num = 0; boolean minus = false; while ((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-')) ; if (num == '-') { num = 0; minus = true; } else { num -= '0'; } while (true) { int b = is.read(); if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } } } catch (IOException e) { } return -1; } static char nc() { try { int b = skip(); if (b == -1) return 0; return (char) b; } catch (IOException e) { } return 0; } static double nd() { try { return Double.parseDouble(ns()); } catch (Exception e) { } return 0; } static String ns() { try { int b = skip(); StringBuilder sb = new StringBuilder(); if (b == -1) return ""; sb.append((char) b); while (true) { b = is.read(); if (b == -1) return sb.toString(); if (b <= ' ') return sb.toString(); sb.append((char) b); } } catch (IOException e) { } return ""; } public static char[] ns(int n) { char[] buf = new char[n]; try { int b = skip(), p = 0; if (b == -1) return null; buf[p++] = (char) b; while (p < n) { b = is.read(); if (b == -1 || b <= ' ') break; buf[p++] = (char) b; } return Arrays.copyOf(buf, p); } catch (IOException e) { } return null; } public static byte[] nse(int n) { byte[] buf = new byte[n]; try { int b = skip(); if (b == -1) return null; is.read(buf); return buf; } catch (IOException e) { } return null; } static int skip() throws IOException { int b; while ((b = is.read()) != -1 && !(b >= 33 && b <= 126)) ; return b; } static boolean eof() { try { is.mark(1000); int b = skip(); is.reset(); return b == -1; } catch (IOException e) { return true; } } static int ni() { try { int num = 0; boolean minus = false; while ((num = is.read()) != -1 && !((num >= '0' && num <= '9') || num == '-')) ; if (num == '-') { num = 0; minus = true; } else { num -= '0'; } while (true) { int b = is.read(); if (b >= '0' && b <= '9') { num = num * 10 + (b - '0'); } else { return minus ? -num : num; } } } catch (IOException e) { } return -1; } static long mod =1_000_000_000+7; static void solver(){ long n=nl(); int p=ni(); int c=ni(); //まず、さいころをP+C個振って和がK個になるパターン数をDPで数える。 long[][] k=new long[p+c+1][13*(p+c)+1]; k[0][0]=1; int[] prime={2,3,5,7,11,13}; int[] composite={4,6,8,9,10,12}; for(int l=0;l<6;l++){ for(int i=0;i0){ k[i+1][j+prime[l]]+=k[i][j]; k[i+1][j+prime[l]]%=mod; } } } } for(int l=0;l<6;l++){ for(int i=0;i0){ k[p+i+1][j+composite[l]]+=k[p+i][j]; k[p+i+1][j+composite[l]]%=mod; } } } } int n_k=k[0].length-1; long[][] A=new long[n_k][n_k]; for(int i=0;i-k[0].length;j--){ //-jから出発した場合 if(i+j>=1){ a[i+j-1][0]+=k[p+c][i]; a[i+j-1][0]%=mod; } } } for(int i=0;i=0;j--){ a[i][0]+=(k[p+c][i-j]*a[j][0])%mod; a[i][0]%=mod; } } long[] e=new long[a.length]; for(int i=0;i0;n>>=1,x=mul(x,x,e,mod)){ if((n&1)==1)y=mul(y,x,e,mod); } long ans=0; for(int i=0;i=K;i--){ for(j=1;j<=K;j++){ c[i-j]=(c[i-j]+e[j-1]*c[i])%mod; } } long[] d=new long[K]; for(i=0;i