#include <bits/stdc++.h>
using namespace std;
const int mdl = 1000000007LL;
string s;
int n, gap;
vector<int> sa, pos, satmp, lcp;
bool cmp(int i, int j) {
  if (pos[i] != pos[j]) return pos[i] < pos[j];
  i += gap;
  j += gap;
  if (i < n && j < n) return pos[i] < pos[j];
  return i > j;
}
void buildsa() {
  n = (int((s).size()));
  sa = pos = satmp = lcp = vector<int>(n, 0);
  for (int i = 0; i < (n); ++i) {
    sa[i] = i;
    pos[i] = s[i];
  }
  for (gap = 1;; gap *= 2) {
    sort((sa).begin(), (sa).end(), cmp);
    satmp[0] = 0;
    for (int i = 0; i < (n - 1); ++i)
      satmp[i + 1] = satmp[i] + cmp(sa[i], sa[i + 1]);
    for (int i = 0; i < (n); ++i) pos[sa[i]] = satmp[i];
    if (satmp[n - 1] == n - 1) break;
  }
}
void buildlcp() {
  int k = 0;
  for (int i = 0; i < (n); ++i) {
    if (pos[i] == n - 1) continue;
    for (int j = sa[pos[i] + 1]; i + k < n && j + k < n && s[i + k] == s[j + k];
         ++k)
      ;
    lcp[pos[i]] = k;
    if (k) --k;
  }
}
string x;
vector<vector<int> > wtdup, spaup, minlcp;
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> x;
  s = x;
  buildsa();
  buildlcp();
  int n = (int((x).size()));
  wtdup.resize(n + 1, vector<int>(n + 1, 0));
  spaup.resize(n + 1, vector<int>(n + 1, -1));
  minlcp.resize(n + 1, vector<int>(n + 1, 1000000000));
  for (int i = 0; i < (n - 1); ++i) {
    minlcp[i][i] = lcp[i];
    for (int j = i + 1; j < n - 1; ++j)
      minlcp[i][j] = min(lcp[j], minlcp[i][j - 1]);
  }
  int critst, crited;
  vector<int> spsol(n + 1, -1);
  for (int ed = 0; ed < (n); ++ed) {
    for (int st = ed; st >= 0; st--) {
      if (x[st] == '0') {
        wtdup[ed][st] = wtdup[ed][st + 1];
        spaup[ed][st] = spaup[ed][st + 1];
        continue;
      }
      crited = st - 1;
      critst = crited + (st - ed);
      if (st == 0) {
        wtdup[ed][st] = (wtdup[ed][st + 1] + 1);
        if (wtdup[ed][st] == mdl) wtdup[ed][st] = 0;
        spaup[ed][st] = 1;
        spsol[0] = 1;
        continue;
      }
      if (critst >= 0) {
        if (pos[st] < pos[critst] &&
            minlcp[pos[st]][pos[critst] - 1] <= ed - st)
          ++critst;
      } else
        critst = 0;
      wtdup[ed][st] = wtdup[ed][st + 1] + wtdup[crited][critst];
      if (wtdup[ed][st] >= mdl) wtdup[ed][st] -= mdl;
      spaup[ed][st] = 1 + spaup[crited][critst];
      if (spaup[ed][st] == 0) spaup[ed][st] = -1;
      spsol[st] = spaup[ed][st];
      if (spaup[ed][st] == -1)
        spaup[ed][st] = spaup[ed][st + 1];
      else {
        if (spaup[ed][st + 1] != -1)
          spaup[ed][st] = min(spaup[ed][st], spaup[ed][st + 1]);
      }
    }
  }
  cout << wtdup[n - 1][0] << endl;
  int bst = mdl + 3;
  for (int i = n - 1; i >= 0; i--) {
    if (n - 1 - i >= 20 && bst != mdl + 3) break;
    if (spsol[i] == -1) continue;
    int cloc = i;
    int cn = 0;
    while (cloc <= n - 1) {
      cn *= 2;
      cn += (x[cloc] - '0');
      cn %= mdl;
      ++cloc;
    }
    cn += spsol[i];
    cn %= mdl;
    bst = min(bst, cn);
  }
  cout << bst % mdl << endl;
  return 0;
}
