#include #include using namespace std; using namespace atcoder; // デバッグ表示 #define dump(x) cout << #x << ":" << (x) << endl; // 型定義 typedef long long ll; typedef pair P; // forループ #define REP(i,n) for(ll i=0; i<(ll)(n); ++i) // 定数宣言 const int INF = 1e9; const int MOD = 1e9+7; const ll LINF = 1e18; // modint using mint = modint1000000007; // グラフ表現 using Graph = vector>; // グラフの辺表現 using Edge = map,int>; // n次元配列の初期化。第2引数の型のサイズごとに初期化していく。 template void Fill(A (&array)[N], const T &val){ std::fill( (T*)array, (T*)(array+N), val ); } // 最大公約数 ll gcd(ll a,ll b){ if (a%b == 0) return(b); else return(gcd(b, a%b)); } // 最小公倍数 ll lcm(ll a, ll b){ return a/gcd(a, b) * b; } // dp[i][smaller] 前からi桁目まで見たときの合計スコア // smallerが1なら既にそれよりも小さいことが確定している mint dp[100005][2]; int main() { cout << fixed << setprecision(15); string S; cin >> S; ll N = S.length(); // dp[0][0] = 1; dp[0][0] = 1; for(int i = 0; i < N; i++){ ll a = S[i] - '0'; ll d = a * (a-1) / 2; // まだ小さいことが確定していないとき dp[i+1][0] = dp[i][0] * mint(a); // 小さいことが確定した更新 dp[i+1][1] += dp[i][0] * mint(d); dp[i+1][1] += dp[i][1] * mint(45); // 0003みたいなときにこれは0でなく3になるので1桁分を加算しないといけない if(i >= 1){ dp[i+1][1] += mint(45); } // dump(i); // dump(dp[i+1][0].val()); // dump(dp[i+1][1].val()); } cout << (dp[N][0]+dp[N][1]).val() << endl; // dump(dp[1][1]); return 0; }