// clang-format off
	#define BADSEED chrono::high_resolution_clock::now().time_since_epoch().count()
	#include <bits/stdc++.h>
	using namespace std;
	using uint = unsigned int;
	#define TM_(...) template <class __VA_ARGS__>
	#define ENABLE(...) TM_(T) static enable_if_t<__VA_ARGS__>
	#define SFINAE(name, ...)                                                  \
		TM_(, class = void) struct name##_s : false_type {};                   \
		TM_(T) struct name##_s<T, decltype(void(__VA_ARGS__))> : true_type {}; \
		TM_(T) constexpr bool name = name##_s<T>::value;
	ostream &operator<<(ostream &os, int8_t c) { return os << static_cast<int>(c); }
	namespace narut {
		TM_(T) using TupSz = tuple_size<decay_t<T>>;
		SFINAE(Iterable, begin(declval<T &>()))
		SFINAE(IsTuple, TupSz<T>{})
		SFINAE(Coutable, cout << declval<T &>())
		SFINAE(Cinable, cin >> declval<T &>())
		TM_(T) constexpr char Spc(T &&) { return (Iterable<T> or IsTuple<T>) ? '\n' : ' '; }
		template <ostream &os, bool Red> struct Writer {
			ENABLE(Coutable<T>) Write(T const &t) { os << t; }
			ENABLE(!Coutable<T> and Iterable<T>) Write(T const &t) {
				auto it = begin(t), e = end(t);
				if (it != e) Write(*it++);
				for (; it != e; Write(*it++)) os << Spc(*it);
			}
			TM_(T, size_t... Is) static void WriteTup(T const &t, index_sequence<Is...>) {
				(void)(int[]){0, ((Is == 0) ? 0 : ((os << ' '), 0), Write(get<Is>(t)), 0)...};
			}
			ENABLE(!Coutable<T> and !Iterable<T> and IsTuple<T>) Write(T const &t) {
				WriteTup(t, make_index_sequence<TupSz<T>::value>{});
			}
			void operator()() const { os << '\n'; }
			TM_(F, class... Ts) void operator()(F const &f, Ts const &... ts) {
				if (Red) os << "\033[0;31m";
				Write(f);
				(void)(int[]){0, (os << ' ', Write(ts), 0)...};
				if (Red)
					os << "\033[0m\n";
				else
					os << '\n';
			}
		};
		struct Cin {
			ENABLE(Cinable<T>) Read(T &t) { cin >> t; }
			ENABLE(!Cinable<T> and Iterable<T>) Read(T &t) {
				for (auto &&x : t) Read(x);
			}
			TM_(T, size_t... Is) static void ReadTup(T &t, index_sequence<Is...>) {
				(void)(int[]){0, (Read(get<Is>(t)), 0)...};
			}
			ENABLE(!Cinable<T> and !Iterable<T> and IsTuple<T>) Read(T &t) {
				ReadTup(t, make_index_sequence<TupSz<T>::value>{});
			}
			TM_(T) void operator()(T &t) const { Read(t); }
			TM_(T) void operator()(T &t, uint n) const { t.resize(n), Read(t); }
			TM_(T) operator T() const {
				T t;
				return Read(t), t;
			}
		};
		struct Big {
			TM_(T) constexpr operator T() const {
				return 0x3f3f3f3f3f3f3f3f & numeric_limits<T>::max();
			}
		};
		TM_(T, size_t N, size_t... Ns) struct arr {
			using type = array<typename arr<T, Ns...>::type, N>;
		};
		TM_(T, size_t N) struct arr<T, N> { using type = array<T, N>; };
		TM_(T, size_t N, size_t... Ns) using Arr = typename arr<T, N, Ns...>::type;
		template <class C, class T> auto Fill(C &c, T const &t) -> decltype(void(*begin(c) = t)) {
			fill(begin(c), end(c), t);
		}
		template <class C, class T> auto Fill(C &c, T const &t) -> decltype(void(begin(*begin(c)))) {
			for (auto &x : c) Fill(x, t);
		}
	} // namespace narut
	narut::Cin Cin;
	narut::Writer<cout, false> Cout;
	narut::Big Big;
	using narut::Arr;
	using narut::Fill;
	using ll = long long;
	#define FOR(i, j, n) for (int i = static_cast<int>(j); i < static_cast<int>(n); ++i)
	#define ROF(i, j, n) for (int i = static_cast<int>(n) - 1; i >= static_cast<int>(j); --i)
	#ifdef NARUT_LOCAL
	narut::Writer<cerr, true> Cerr;
	#define DBG(...) __VA_ARGS__
	#define Debug(...) Cerr(__VA_ARGS__)
	#else
	#define Debug(...) 0
	#define DBG(...)
	#endif
	#ifndef BADSEED
	#define BADSEED random_device{}()
	#endif

// clang-format on
// STUCK : READ THE PROBLEM CAREFULLY. LOOK AT ALL THE CONSTRAINTS

template <class T, class AddT, class MultT, T P> struct ModNum {
	using value_type = T;
	using add_type = AddT;
	using mult_type = MultT;
	constexpr static value_type mod_value = P;

	T val = 0;
	constexpr ModNum() = default;
	constexpr ModNum(T x) : val(x) {}
	template <class S> static constexpr ModNum Safe(S x) {
		return static_cast<T>(((x % P) + P) % P);
	}
	explicit constexpr operator value_type const &() const { return val; }

	constexpr bool operator==(ModNum rhs) const { return val == rhs.val; }
	constexpr bool operator!=(ModNum rhs) const { return val != rhs.val; }
	constexpr ModNum operator-() const { return (val == 0) ? (*this) : (P - val); }

	constexpr ModNum &operator+=(ModNum rhs) { return *this = Add(val, rhs.val); }
	constexpr ModNum &operator-=(ModNum rhs) { return *this = Sub(val, rhs.val); }
	constexpr ModNum &operator*=(ModNum rhs) { return *this = Mult(val, rhs.val); }
	constexpr ModNum &operator/=(ModNum rhs) { return *this *= rhs.Inverse(); }

	template <class S> constexpr ModNum Pow(S ex) const {
		if (P == 1) return 0;
		if (ex < 0) return Pow(-ex).Inverse();
		ModNum result = 1;
		ModNum base(*this);
		while (ex > 0) {
			if (ex & 1) result *= base;
			ex >>= 1;
			base *= base;
		}
		return result;
	}
	constexpr ModNum Inverse() const { return Pow(P - 2); }
	friend constexpr ModNum operator+(ModNum lhs, ModNum rhs) { return Add(lhs.val, rhs.val); }
	friend constexpr ModNum operator-(ModNum lhs, ModNum rhs) { return Sub(lhs.val, rhs.val); }
	friend constexpr ModNum operator*(ModNum lhs, ModNum rhs) { return Mult(lhs.val, rhs.val); }
	friend constexpr ModNum operator/(ModNum lhs, ModNum rhs) { return lhs * rhs.Inverse(); }

  private:
	static constexpr T Add(AddT lhs, AddT rhs) {
		auto sum = lhs + rhs;
		return (sum < P) ? sum : (sum - P);
	}
	static constexpr T Sub(AddT lhs, AddT rhs) {
		auto dif = lhs - rhs;
		return (dif >= 0) ? dif : (dif + P);
	}
	static constexpr T Mult(MultT lhs, MultT rhs) { return static_cast<T>((lhs * rhs) % P); }
	friend ostream &operator<<(ostream &os, ModNum m) { return os << m.val; }
	friend istream &operator>>(istream &is, ModNum &m) {
		is >> m.val;
		return is;
	}
};
using Num = ModNum<int, int, int64_t, 1000000007>;
using Z13 = ModNum<int, int, int, 13>;

string S;

auto Run() {
	cin >> S;

	reverse(begin(S), end(S));

	array<Num, 13> dp{};
	array<Z13, 6> cycle = {1, 10, 9, 12, 3, 4};

	dp[0] = 1;

	int const n = S.size();
	FOR(i, 0, n) {
		array<Num, 13> tmp{};
		auto z = cycle[i % 6];
		if (S[i] == '?') {
			FOR(x, 0, 10) {
				FOR(j, 0, 13) { tmp[(z * x + j).val] += dp[j]; }
			}
		} else {
			int x = S[i] - '0';
			FOR(j, 0, 13) { tmp[(z * x + j).val] += dp[j]; }
		}
		dp = tmp;
		Debug(dp);
	}
	cout << dp[5];
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(10);
#ifdef NARUT_LOCAL
	cerr << fixed << setprecision(10);
	assert(freopen("./io/test.in", "r", stdin));
	// assert(freopen("./io/test.out", "w", stdout));
#endif

	Run();
}


Measured memory_bytes: 512