#include<bits/stdc++.h>
#include <queue> 
#include<map>
#include <string>
#define ll long long
#define ull unsigned long long 
#define pp push_back
#define bitc  __builtin_popcountl
#define mp make_pair
#define fr(i,a,b) for (int i = (a), _b = (b); i <= _b; i++)
#define frr(i,a,b) for (int i = (a), _b = (b); i >= _b; i--)
#define rep(i,n) for (int i = 0, _n = (n); i < _n; i++)
#define repr(i,n) for (int i = n - 1; i >= 0; i--)
#define fill(ar,val) memset(ar, val, sizeof(ar))
#define fill0(ar) fill((ar), 0)
#define MAXN   100010 
#define MOD 1000000007
#define debug(x) cout<<#x<<": "<<x<<endl
#define dbug(x) cout<<#x<<": "<<x<<" "
#define fi first
#define se second
# define INF 0x3f3f3f3f
//const int dx[]={0,0,-1,1},dy[]={-1,1,0,0};



using namespace std;
//gcd
ll Gcd(ll a,ll b){
    if(a%b==0) return b;
    return Gcd(b,a%b);
}
//max
ll Max(ll a,ll b){
    if(a>b)
    return a;
    return b;
}
//min
ll Min(ll a,ll b){
    if(a<b)
    return a;
    return b;
}


ll findlcm(vector<ll> arr, ll n) 
{ 
    // Initialize result 
    ll ans = arr[0]; 
  
    // ans contains LCM of arr[0], ..arr[i] 
    // after i'th iteration, 
    for (int i = 1; i < n; i++) 
        ans = (((arr[i] * ans)) / 
                (Gcd(arr[i], ans))); 
  
    return ans; 
} 


ll gcdExtended(ll a, ll b, ll *x, ll *y)
{
    // Base Case
    if (a == 0)
    {
        *x = 0, *y = 1;
        return b;
    }
 
    ll x1, y1; 
    ll gcd = gcdExtended(b%a, a, &x1, &y1);
 
    *x = y1 - (b/a) * x1;
    *y = x1;
 
    return gcd;
}




   
 
 ll power(ll x, ll y, ll p) 
{ 
    ll res = 1;      
    x = x % p;  
    while (y > 0) 
    { 
        if (y & 1) 
            res = (res*x) % p; 
  
        y = y>>1; 
        x = (x*x) % p;   
    } 
    return res; 
} 






ll modInverse(ll a, ll m)
{
    ll x, y;
    ll g = gcdExtended(a, m, &x, &y);
    if (g != 1)
        return -1 ;
    else
    {
        
        ll res = (x%m + m) % m;
        return res;
    }
}





vector<ll> primeFactors(ll n)
{    
    vector<ll> v;
    while (n%2 == 0)
    {
        v.push_back(2);
        n = n/2;
    }
    for (int i = 3; i <= sqrt(n); i = i+2)
    {
        while (n%i == 0)
        {
            v.push_back(i);
            n = n/i;
        }
    }

    if (n > 2)
        v.push_back(n);
        return v;
}




//ll C[2001][2000]; 
/*
void binomialCoeff(ll n, ll k) 
{ 
   
    ll i, j; 
  
    // Caculate value of Binomial Coefficient in bottom up manner 
    for (i = 0; i <= n; i++) 
    { 
        for (j = 0; j <= k; j++) 
        { 
            // Base Cases 
            if (j == 0 || j == i) 
                C[i][j] = 1; 
  
            // Calculate value using previosly stored values 
            else
                C[i][j] = (C[i-1][j-1]%MOD + C[i-1][j]%MOD)%MOD; 
        } 
    } 
  
    //return C[n][k]; 
} 
*/






  
//ll spf[MAXN]; 
  /*
void sieve() 
{ 
    spf[1] = 1; 
    for (int i=2; i<MAXN; i++) 
      spf[i] = i; 
   for (int i=4; i<MAXN; i+=2) 
        spf[i] = 2; 
  
    for (int i=3; i*i<MAXN; i++) 
    { 
        if (spf[i] == i) 
        { 
           for (int j=i*i; j<MAXN; j+=i) 
                if (spf[j]==j) 
                    spf[j] = i; 
        } 
    } 
} 


*/

ll binarySearch(ll arr[], ll l, ll r, ll x)
{
   if (r >= l)
   {
        ll mid = l + (r - l)/2;
        if (arr[mid] == x)  
            return mid;
 
        if (arr[mid] > x) 
            return binarySearch(arr, l, mid-1, x);
 
        return binarySearch(arr, mid+1, r, x);
   }
 
   return -1;
}


//Segment Tree Implementation

         // const ll N = 100000; 
 
//ll n; 
 
         //  ll tree[2 * N];
/*
void build( ll arr[]) 
{ 
    for (ll i=0; i<n; i++)    
        { tree[n+i] = arr[i];
           
         }
     
    for (ll i = n - 1; i > 0; --i)     
        {tree[i] = tree[i<<1] + tree[i<<1 | 1];    
               cout<<"i<<1  is "<<(i<<1)<<endl;
               cout<<"i<<1 | 1  is "<<(i<<1 | 1)<<endl;
         }
}
*/
 /*
void updateTreeNode(ll p, ll value) 
{ 
    tree[p+n] = value;
    p = p+n;
     
    for (ll i=p; i > 1; i >>= 1)
        {tree[i>>1] = tree[i] + tree[i^1];
           }
}
 
ll query(ll l, ll r) 
{ 
    ll res = 0;
     
    for (l += n, r += n; l < r; l >>= 1, r >>= 1)
    {
        if (l&1) 
           {    
               res += tree[l++];
               
               }    
        if (r&1) 
             {   res += tree[--r];
                 
            }
    }
     
    return res;
}
*/

//Dijkstra's Algorithm

vector<ll> shortPath( vector<pair<ll,ll> > v[],ll src,ll V=0) 
{ 
     set< pair<ll,ll> > setds; 
  
    ll sizee=V;
    ll IN=0x3f3f3f3f;
    vector<ll> dist(sizee, IN); 
  
    setds.insert(make_pair(0, src)); 
    dist[src] = 0; 
  
    while (!setds.empty()) 
    { 
        pair<ll, ll> tmp = *(setds.begin()); 
        cout<<tmp.first<<" ";
        setds.erase(setds.begin()); 
  
        ll u = tmp.second; 
  
        vector< pair<ll, ll> >::iterator i; 
        for (i = v[u].begin(); i != v[u].end(); ++i) 
        { 
            ll v = (*i).first; 
            ll weight = (*i).second; 
      if (dist[v] > dist[u] + weight) 
            { 
                if (dist[v] != INF) 
                    setds.erase(setds.find(make_pair(dist[v], v))); 
  
                dist[v] = dist[u] + weight; 
                setds.insert(make_pair(dist[v], v)); 
            } 
        } 
    }
    return dist;
} 


// Sieve Implementation
/* 
for (ll i=2;i<=100005;i++)
        if (p[i]==0)
        for (ll j=2*i;j<=100005;j+=i) p[j]=1; */


// Dfs search

void dfs(std::vector<ll> v[],ll s,bool visited[])
{
    cout<<s+1<<" ";
    visited[s]=true;
   // cout<<s<<"ss"<<visited[3]<<endl;
  for (ll i = 0; i < v[s].size(); ++i)
  {
    if(!visited[v[s][i]] )
    { 
        dfs(v,v[s][i],visited);


    }

  }


}



void bfs(vector<ll> adj[],ll s, bool visited[]){



   ll ret = 0;
  
    // Create a queue for BFS 
    list<int> queue; 
  
    // Mark the current node as visited and enqueue it 
    visited[s] = true; 
    queue.push_back(s); 
  
    // 'i' will be used to get all adjacent 
    // vertices of a vertex 
    list<int>::iterator i; 
    vector<ll>::iterator j;
  
    while(!queue.empty()) 
    { 
        // Dequeue a vertex from queue and print it 
        s = queue.front();
        cout<<s+1<<" "; 
        ret++;
        //cout<<s<<"ss";
        queue.pop_front(); 
  
        // Get all adjacent vertices of the dequeued 
        // vertex s. If a adjacent has not been visited,  
        // then mark it visited and enqueue it 
        for (j = adj[s].begin(); j != adj[s].end(); ++j) 
        { 
            if (!visited[*j]) 
            { 
                visited[*j] = true; 
                queue.push_back(*j); 
            } 
        } 
    }
     
} 










//do not use n , N , C


// Using iterators in C++ 
//set<ll>:: iterator it;
/*
ll lookup[500000][21];
ll table[500000][21];

void buildSparseTableMin(ll arr[], ll n) 
{  
    for (ll i = 0; i < n; i++) 
        lookup[i][0] = arr[i]; 
    for (ll j = 1; (1 << j) <= n; j++) { 
        for (ll i = 0; (i + (1 << j) - 1) < n; i++) { 
            if (lookup[i][j - 1] <  
                        lookup[i + (1 << (j - 1))][j - 1]) 
                lookup[i][j] = lookup[i][j - 1]; 
            else
                lookup[i][j] =  
                         lookup[i + (1 << (j - 1))][j - 1]; 
        } 
    } 
} 
  
ll queryMin(ll L, ll R) 
{ 
    ll j = (ll)log2(R - L + 1); 
  
    if (lookup[L][j] <= lookup[R - (1 << j) + 1][j]) 
        return lookup[L][j]; 
  
    else
        return lookup[R - (1 << j) + 1][j]; 
} 



void buildSparseTableGcd(ll arr[], ll n) 
{ 
    for (ll i = 0; i < n; i++) 
        {table[i][0] = arr[i]; }
    ll k=20;
    for (ll j = 1; j <= k; j++) 
        for (ll i = 0; i <= n - (1 << j); i++) 
            table[i][j] = __gcd(table[i][j - 1], 
                    table[i + (1 << (j - 1))][j - 1]); 
} 

ll queryGcd(ll L, ll R) 
{ 
    ll j = (ll)log2(R - L + 1); 
  return __gcd(table[L][j], table[R - (1 << j) + 1][j]); 
}
*/




void printgraph(std::vector<ll> v[],ll n){
    for( ll i = 0;i<n;i++){
    for(auto l=v[i].begin();l!=v[i].end();l++){
        cout<<i<<" "<<*l<<endl;
    }
}

}

void printvector(std::vector<ll> v){
    for(auto i=v.begin();i!=v.end();i++) cout<<*i<<" ";
        cout<<""<<endl;


}
void printvector(std::vector<int> v){
    for(auto i=v.begin();i!=v.end();i++) cout<<*i<<" ";
        cout<<""<<endl;


}
void printarray(ll arr[],ll n){

    for(ll i =0;i<n;i++) cout<<arr[i]<<" ";
        cout<<""<<endl;
}
void printarray(double arr[],ll n){
    for(ll i =0;i<n;i++) cout<<arr[i]<<" ";
        cout<<""<<endl;

}
void printarray(bool arr[],ll n){
    for(ll i =0;i<n;i++) cout<<arr[i]<<" ";
        cout<<""<<endl;

}
void printarray(int arr[],int n){
    for(ll i =0;i<n;i++) cout<<arr[i]<<" ";
        cout<<""<<endl;

}

void weightedgraph(std::vector<pair<ll,ll>> v[],ll n){
    for(ll i =0;i<n;i++){
        for(auto j=v[i].begin();j!=v[i].end();j++){
            cout<<i<<" "<<(*j).first<<" "<<(*j).second<<endl;
        }
    }

}






  



void dijk(){
    vector<pair<int,int>> v[4];
    v[0].push_back({3,1});
    v[0].push_back({10,3});
    v[1].push_back({1,2});
    v[2].push_back({3,3});
    int dist[4];
    bool visited[4]={false};
   // memset(dist,INT_MAX/10,sizeof(dist));
    //cout<<dist[0]<<endl;
    for(int i=0;i<4;i++) dist[i]=INT_MAX/10;
    multiset<pair<int,int>> s;
    s.insert({0,0});
    dist[0]=0;
    while(!s.empty()){
        pair<int,int> p=*s.begin();
        s.erase(s.begin());
        int vert=p.second;
        int d=p.first;
        if(visited[vert]) continue;
        visited[vert]=true;
        for(int i=0;i<v[vert].size();i++){
            int weight=v[vert][i].first;
            int neigh=v[vert][i].second;
            if(dist[neigh]>dist[vert]+weight){
                dist[neigh]=dist[vert]+weight;
                s.insert({dist[neigh],neigh});
            }
        }
    }

    //for(int i=0;i<4;i++) cout<<dist[i]<<" ";
}


void initialize(int arr[],int size[],int n){
    for(int i=0;i<n;i++){
        arr[i]=i;
        size[i]=1;
       
    }
    return;
}

int root(int arr[],int i){
    while(arr[i]!=i){
        arr[i]=arr[arr[i]];
        i=arr[i];
    }
    return i;
}

int find(int arr[],int a,int b){
    int root_a=root(arr,a);
    int root_b=root(arr,b);
    return root_b==root_a;
}

void Union(int arr[],int size[],int a,int b){
    int root_a=root(arr,a);
    int root_b=root(arr,b);
    
    if(size[root_a]>size[root_b]){
        arr[root_b]=arr[root_a];
        size[root_a]+=size[root_b];

    }
    else{
        arr[root_a]=arr[root_b];
        size[root_b]+=size[root_a];
    }
}

void topo(stack<int>& s,vector<int> arr[],int cur,bool visited[]){
    visited[cur]=true;
    for(int i:arr[cur]){
        if(!visited[i]) topo(s,arr,i,visited);
    }
    s.push(cur);
    return;
}






void solve(){
    string s;
    cin>>s;
    ll n=s.size();
    int i,j,k;
    ll mod=pow(10,9)+7;
    vector<ll> dp(13,0);
    if(s[0]!='?'){
        dp[int(s[0])-int('0')]=1;
    }
    else{
        for(i=0;i<10;i++) dp[i]=1;
    }
    
    //printvector(dp);
    for(i=1;i<n;i++){
        vector<ll> temp(13,0);
        if(s[i]!='?'){
            for(int k=0;k<13;k++){
                int ind=(10*k+int(s[i])-int('0'))%13;
                temp[ind]+=dp[k];
                temp[ind]%=mod;
            }
        }
        else{
            for(j=0;j<10;j++){
                for(int k=0;k<13;k++){
                int ind=(10*k+int(j))%13;
                temp[ind]+=dp[k];
                temp[ind]%=mod;
            }

            }
        }
        dp=temp;
    }
    cout<<dp[5]<<endl;

}



int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
  /*
#ifndef ONLINE_JUDGE
    // for getting input from input.txt
    freopen("input.txt", "r", stdin);
    // for writing output to output.txt
    //freopen("output.txt", "w", stdout);
#endif
*/
    
    solve();
    return 0;
}




Measured memory_bytes: 512