#define md 1000000007
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define INTEGERONLY
#ifdef IALL
  #define int long long
#endif
namespace Template {
  #define FOR(i, x, y) for(int i = (x); i <= (y); ++i)
  #define FORD(i, x, y) for(int i = (x); i >= (y); --i)
  #define MASK(i) (1LL << (i))
  #define COUNT(x) __builtin_popcountll(x)
  #define BIT(x, i) (((x) >> (i)) & 1)
  #define pb push_back
  #define eb emplace_back
  #define Size(v) (int)v.size()
  typedef long long ll;
  typedef long double ld;
  typedef vector<int> vi;
  typedef vector<long long> vll;
  typedef vector<pair<int, int>> vii;
  typedef pair<int, int> ii;
  template <typename T>
  using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
  const double pi = acos(-1);
  struct Point {
    ll x, y;
    Point(): x{0}, y{0} {}
    Point(ll a, ll b): x{a}, y{b} {}
    bool operator<(const Point& other) const {
      return make_pair(x, y) < make_pair(other.x, other.y);
    }
    Point operator-(const Point& other) const {
      return Point(x - other.x, y - other.y);
    }
    ll operator*(const Point& other) const {
      return (x * other.y - y * other.x);
    }
    ll operator%(const Point& other) const {
      return (x * other.x + y * other.y);
    }
    double len() {
      return sqrt((double)x * x + y * y);
    }
  };
  double angle(const Point & a, const Point & b, const Point & c) {return atan2((a - b) * (c - b), (a - b) % (c - b));}
  double dist(const Point & a, const Point & b) {return (b - a).len();}
  ll area2(const Point & a, const Point & b, const Point & c) {return abs((b - a) * (c - a));}
  bool obtuse(const Point & a, const Point & b, const Point & c) {return abs(angle(a, b, c)) > pi / 2;}
  ll eval(Point a, Point b, Point c) {return (b - a) * (c - b);}
  bool cw(Point a, Point b, Point c) {return eval(a, b, c) < 0;}
  bool ccw(Point a, Point b, Point c) {return eval(a, b, c) > 0;}
  void convex_hull(vector<Point> & a) {
    if (Size(a) == 1) return;
    sort(a.begin(), a.end());
    Point p1 = a[0], p2 = a.back();
    vector<Point> up, down;
    up.push_back(p1);
    down.push_back(p1);
    for (int i = 1; i < Size(a); ++i) {
      if (i == Size(a) - 1 || cw(p1, a[i], p2)) {
        while (Size(up) >= 2 && !cw(up[Size(up) - 2], up[Size(up) - 1], a[i])) {
          up.pop_back();
        }
        up.push_back(a[i]);
      }
      if (i == Size(a) - 1 || ccw(p1, a[i], p2)) {
        while (Size(down) >= 2 && !ccw(down[Size(down) - 2], down[Size(down) - 1], a[i])) {
          down.pop_back();
        }
        down.push_back(a[i]);
      }
    }
    a.clear();
    // convex hull in clockwise order
    for (int i = 0; i < Size(up); ++i) a.pb(up[i]);
    for (int i = Size(down) - 2; i > 0; --i) a.pb(down[i]);
  }
  double area(vector<Point> & temp) {
    int n = Size(temp);
    double res = 0;
    for (int i = 0; i < n - 1; ++i) {
      // actually, this represent the vector with root (0, 0) to point temp
      res += temp[i] * temp[i + 1];
    }
    res += temp[n - 1] * temp[0];
    return abs(res) / 2.0;
  }
  ll raw_dist(const Point& a, const Point& b) {
    return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y);
  }
  template <typename T>
  T inverse(T a, T m) {
    T u = 0, v = 1;
    while (a != 0) {
      T t = m / a;
      m -= t * a; swap(a, m);
      u -= t * v; swap(u, v);
    }
    assert(m == 1);
    return u;
  }
  mt19937 mt_rng(chrono::steady_clock::now().time_since_epoch().count());
  ll randint(ll a, ll b) {
    return uniform_int_distribution<ll>(a, b)(mt_rng);
  }
  template <typename T>
  class Modular {
   public:
    using Type = typename decay<decltype(T::value)>::type;
    constexpr Modular() : value() {}
    template <typename U>
    Modular(const U& x) {
      value = normalize(x);
    }
    template <typename U>
    static Type normalize(const U& x) {
      Type v;
      if (-mod() <= x && x < mod()) v = static_cast<Type>(x);
      else v = static_cast<Type>(x % mod());
      if (v < 0) v += mod();
      return v;
    }
    const Type& operator()() const { return value; }
    template <typename U>
    explicit operator U() const { return static_cast<U>(value); }
    constexpr static Type mod() { return T::value; }
    Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; }
    Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; }
    template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); }
    template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); }
    Modular& operator++() { return *this += 1; }
    Modular& operator--() { return *this -= 1; }
    #ifdef IALL
      #undef int
    #endif
    Modular operator++(int) { Modular result(*this); *this += 1; return result; }
    Modular operator--(int) { Modular result(*this); *this -= 1; return result; }
    Modular operator-() const { return Modular(-value); }
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) {
    #ifdef IALL
      #define int long long
    #endif
  #ifdef _WIN32
      uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
      uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
      asm(
        "divl %4; \n\t"
        : "=a" (d), "=d" (m)
        : "d" (xh), "a" (xl), "r" (mod())
      );
      value = m;
  #else
      value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
  #endif
      return *this;
    }
    #ifdef IALL
      #define int long long
    #endif
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, ll>::value, Modular>::type& operator*=(const Modular& rhs) {
      ll q = static_cast<ll>(static_cast<ld>(value) * rhs.value / mod());
      value = normalize(value * rhs.value - q * mod());
      return *this;
    }
    template <typename U = T>
    typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) {
      value = normalize(value * rhs.value);
      return *this;
    }
    Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); }
    friend const Type& abs(const Modular& x) { return x.value; }
    template <typename U>
    friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename U>
    friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename V, typename U>
    friend V& operator>>(V& stream, Modular<U>& number);
   private:
    Type value;
  };
  template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; }
  template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); }
  template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; }
  template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; }
  template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template<typename T, typename U>
  Modular<T> power(const Modular<T>& a, const U& b) {
    assert(b >= 0);
    Modular<T> x = a, res = 1;
    U p = b;
    while (p > 0) {
      if (p & 1) res *= x;
      x *= x;
      p >>= 1;
    }
    return res;
  }
  template <typename T>
  bool IsZero(const Modular<T>& number) {
    return number() == 0;
  }
  template <typename T>
  string to_string(const Modular<T>& number) {
    return to_string(number());
  }
  template <typename U, typename T>
  U& operator<<(U& stream, const Modular<T>& number) {
    return stream << number();
  }
  template <typename U, typename T>
  U& operator>>(U& stream, Modular<T>& number) {
    typename common_type<typename Modular<T>::Type, ll>::type x;
    stream >> x;
    number.value = Modular<T>::normalize(x);
    return stream;
  }
  using Mint = Modular<std::integral_constant<decay<decltype(md)>::type, md>>;
  inline void set_precision(const int& x) {cout << fixed << setprecision(x);}
  #ifdef INTEGERONLY
    inline void read(Mint & x) {char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=x*10+c-48;if(nega) x=-x;}
    inline void writep(const Mint & _x){int x=(int)_x;if(x>9) writep(x/10);putchar(x%10+48);}
    inline void write(const Mint & _x) {int x=(int)_x;if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    inline void writeln(const Mint & x) {write(x);putchar('\n');}
    inline void sysout(const Mint & x) {cout << x;}
    template <typename T> inline void read(T &x){char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=(x<<3)+(x<<1)+c-48;if(nega) x=-x;}
    template <typename T> inline void writep(const T & x){if(x>9) writep(x/10);putchar(x%10+48);}
    template <typename T> inline void write(T x){if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    template <typename T> inline void writeln(const T & x){write(x);putchar('\n');}
    template<class H, class... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
    }
    template<class H, class... T> inline void write(const H& h, const T&... t) {
      write(h);
      write(t...);
    }
    template<class H, class... T> inline void writeln(const H& h, const T&... t) {
      write(h);
      write(t...);
      putchar('\n');
    }
  #endif
  #ifndef INTEGERONLY
    template<typename T> inline void read(T& x) {cin >> x;}
    template<typename T> inline void write(const T& x) {cout << x << ' ';}
    template<typename T> inline void writeln(const T& x) {cout << x << '\n';}
    template<typename H, typename... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
  }
  template<typename H, typename... T> inline void write(const H& h, const T&... t) {
    write(h);
    write(t...);
  }
  template<typename H, typename... T> inline void writeln(const H& h, const T&... t) {
    write(h);
    write(t...);
    cout << '\n';
  }
  #endif
  template <typename T>
  __attribute__((always_inline)) void chmax(T& a, const T& b) {a=a<b?b:a;}
  template<typename T>
  __attribute__((always_inline)) void chmin(T& a, const T& b) {a=a<b?a:b;}
  void debug_out() {cerr << endl;}
  template <typename Head, typename... Tail>
  void debug_out(Head H, Tail... T) {
    cerr << " " << std::to_string(H);
    debug_out(T...);
  }
  #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
}
using namespace Template;

ll n, m;
Mint cur;
bool quit = false;

Mint get(int l, int r) {
	return Mint(l + r) * (r - l + 1) / 2;
}

inline void solve(ll l, ll r) {
	if (quit) return;
	if (r >= m) {
		r = m;
		quit = true;
	}
	ll val = n / l;
	cur -= Mint(val) * get(l, r);
}

inline void decompose_into_segments(ll i) {
	ll k = 1;
	while (k <= i) {
		if (quit) return;
		ll first = k;
		ll q = i / k;
		ll second = i / q;
		k = second + 1;
		solve(first, second);
	}
}

int32_t main() {
    #define filename ""
    if (fopen(filename".INP", "r")) {
        freopen(filename".INP", "r", stdin);
        freopen(filename".OUT", "w", stdout);
    }
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    read(n, m);
    // n*min(n,m) - [n/1]*1 -[n/2]*2 - ...
    cur = Mint(n)*min(n, m);
    decompose_into_segments(n);
    if (n < m) cur += Mint(n) * (m - n);

    write(cur);

    return 0;
}


#define md 1000000007
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define INTEGERONLY
#ifdef IALL
  #define int long long
#endif
namespace Template {
  #define FOR(i, x, y) for(int i = (x); i <= (y); ++i)
  #define FORD(i, x, y) for(int i = (x); i >= (y); --i)
  #define MASK(i) (1LL << (i))
  #define COUNT(x) __builtin_popcountll(x)
  #define BIT(x, i) (((x) >> (i)) & 1)
  #define pb push_back
  #define eb emplace_back
  #define Size(v) (int)v.size()
  typedef long long ll;
  typedef long double ld;
  typedef vector<int> vi;
  typedef vector<long long> vll;
  typedef vector<pair<int, int>> vii;
  typedef pair<int, int> ii;
  template <typename T>
  using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
  const double pi = acos(-1);
  struct Point {
    ll x, y;
    Point(): x{0}, y{0} {}
    Point(ll a, ll b): x{a}, y{b} {}
    bool operator<(const Point& other) const {
      return make_pair(x, y) < make_pair(other.x, other.y);
    }
    Point operator-(const Point& other) const {
      return Point(x - other.x, y - other.y);
    }
    ll operator*(const Point& other) const {
      return (x * other.y - y * other.x);
    }
    ll operator%(const Point& other) const {
      return (x * other.x + y * other.y);
    }
    double len() {
      return sqrt((double)x * x + y * y);
    }
  };
  double angle(const Point & a, const Point & b, const Point & c) {return atan2((a - b) * (c - b), (a - b) % (c - b));}
  double dist(const Point & a, const Point & b) {return (b - a).len();}
  ll area2(const Point & a, const Point & b, const Point & c) {return abs((b - a) * (c - a));}
  bool obtuse(const Point & a, const Point & b, const Point & c) {return abs(angle(a, b, c)) > pi / 2;}
  ll eval(Point a, Point b, Point c) {return (b - a) * (c - b);}
  bool cw(Point a, Point b, Point c) {return eval(a, b, c) < 0;}
  bool ccw(Point a, Point b, Point c) {return eval(a, b, c) > 0;}
  void convex_hull(vector<Point> & a) {
    if (Size(a) == 1) return;
    sort(a.begin(), a.end());
    Point p1 = a[0], p2 = a.back();
    vector<Point> up, down;
    up.push_back(p1);
    down.push_back(p1);
    for (int i = 1; i < Size(a); ++i) {
      if (i == Size(a) - 1 || cw(p1, a[i], p2)) {
        while (Size(up) >= 2 && !cw(up[Size(up) - 2], up[Size(up) - 1], a[i])) {
          up.pop_back();
        }
        up.push_back(a[i]);
      }
      if (i == Size(a) - 1 || ccw(p1, a[i], p2)) {
        while (Size(down) >= 2 && !ccw(down[Size(down) - 2], down[Size(down) - 1], a[i])) {
          down.pop_back();
        }
        down.push_back(a[i]);
      }
    }
    a.clear();
    // convex hull in clockwise order
    for (int i = 0; i < Size(up); ++i) a.pb(up[i]);
    for (int i = Size(down) - 2; i > 0; --i) a.pb(down[i]);
  }
  double area(vector<Point> & temp) {
    int n = Size(temp);
    double res = 0;
    for (int i = 0; i < n - 1; ++i) {
      // actually, this represent the vector with root (0, 0) to point temp
      res += temp[i] * temp[i + 1];
    }
    res += temp[n - 1] * temp[0];
    return abs(res) / 2.0;
  }
  ll raw_dist(const Point& a, const Point& b) {
    return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y);
  }
  template <typename T>
  T inverse(T a, T m) {
    T u = 0, v = 1;
    while (a != 0) {
      T t = m / a;
      m -= t * a; swap(a, m);
      u -= t * v; swap(u, v);
    }
    assert(m == 1);
    return u;
  }
  mt19937 mt_rng(chrono::steady_clock::now().time_since_epoch().count());
  ll randint(ll a, ll b) {
    return uniform_int_distribution<ll>(a, b)(mt_rng);
  }
  template <typename T>
  class Modular {
   public:
    using Type = typename decay<decltype(T::value)>::type;
    constexpr Modular() : value() {}
    template <typename U>
    Modular(const U& x) {
      value = normalize(x);
    }
    template <typename U>
    static Type normalize(const U& x) {
      Type v;
      if (-mod() <= x && x < mod()) v = static_cast<Type>(x);
      else v = static_cast<Type>(x % mod());
      if (v < 0) v += mod();
      return v;
    }
    const Type& operator()() const { return value; }
    template <typename U>
    explicit operator U() const { return static_cast<U>(value); }
    constexpr static Type mod() { return T::value; }
    Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; }
    Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; }
    template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); }
    template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); }
    Modular& operator++() { return *this += 1; }
    Modular& operator--() { return *this -= 1; }
    #ifdef IALL
      #undef int
    #endif
    Modular operator++(int) { Modular result(*this); *this += 1; return result; }
    Modular operator--(int) { Modular result(*this); *this -= 1; return result; }
    Modular operator-() const { return Modular(-value); }
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) {
    #ifdef IALL
      #define int long long
    #endif
  #ifdef _WIN32
      uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
      uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
      asm(
        "divl %4; \n\t"
        : "=a" (d), "=d" (m)
        : "d" (xh), "a" (xl), "r" (mod())
      );
      value = m;
  #else
      value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
  #endif
      return *this;
    }
    #ifdef IALL
      #define int long long
    #endif
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, ll>::value, Modular>::type& operator*=(const Modular& rhs) {
      ll q = static_cast<ll>(static_cast<ld>(value) * rhs.value / mod());
      value = normalize(value * rhs.value - q * mod());
      return *this;
    }
    template <typename U = T>
    typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) {
      value = normalize(value * rhs.value);
      return *this;
    }
    Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); }
    friend const Type& abs(const Modular& x) { return x.value; }
    template <typename U>
    friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename U>
    friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename V, typename U>
    friend V& operator>>(V& stream, Modular<U>& number);
   private:
    Type value;
  };
  template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; }
  template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); }
  template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; }
  template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; }
  template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template<typename T, typename U>
  Modular<T> power(const Modular<T>& a, const U& b) {
    assert(b >= 0);
    Modular<T> x = a, res = 1;
    U p = b;
    while (p > 0) {
      if (p & 1) res *= x;
      x *= x;
      p >>= 1;
    }
    return res;
  }
  template <typename T>
  bool IsZero(const Modular<T>& number) {
    return number() == 0;
  }
  template <typename T>
  string to_string(const Modular<T>& number) {
    return to_string(number());
  }
  template <typename U, typename T>
  U& operator<<(U& stream, const Modular<T>& number) {
    return stream << number();
  }
  template <typename U, typename T>
  U& operator>>(U& stream, Modular<T>& number) {
    typename common_type<typename Modular<T>::Type, ll>::type x;
    stream >> x;
    number.value = Modular<T>::normalize(x);
    return stream;
  }
  using Mint = Modular<std::integral_constant<decay<decltype(md)>::type, md>>;
  inline void set_precision(const int& x) {cout << fixed << setprecision(x);}
  #ifdef INTEGERONLY
    inline void read(Mint & x) {char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=x*10+c-48;if(nega) x=-x;}
    inline void writep(const Mint & _x){int x=(int)_x;if(x>9) writep(x/10);putchar(x%10+48);}
    inline void write(const Mint & _x) {int x=(int)_x;if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    inline void writeln(const Mint & x) {write(x);putchar('\n');}
    inline void sysout(const Mint & x) {cout << x;}
    template <typename T> inline void read(T &x){char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=(x<<3)+(x<<1)+c-48;if(nega) x=-x;}
    template <typename T> inline void writep(const T & x){if(x>9) writep(x/10);putchar(x%10+48);}
    template <typename T> inline void write(T x){if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    template <typename T> inline void writeln(const T & x){write(x);putchar('\n');}
    template<class H, class... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
    }
    template<class H, class... T> inline void write(const H& h, const T&... t) {
      write(h);
      write(t...);
    }
    template<class H, class... T> inline void writeln(const H& h, const T&... t) {
      write(h);
      write(t...);
      putchar('\n');
    }
  #endif
  #ifndef INTEGERONLY
    template<typename T> inline void read(T& x) {cin >> x;}
    template<typename T> inline void write(const T& x) {cout << x << ' ';}
    template<typename T> inline void writeln(const T& x) {cout << x << '\n';}
    template<typename H, typename... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
  }
  template<typename H, typename... T> inline void write(const H& h, const T&... t) {
    write(h);
    write(t...);
  }
  template<typename H, typename... T> inline void writeln(const H& h, const T&... t) {
    write(h);
    write(t...);
    cout << '\n';
  }
  #endif
  template <typename T>
  __attribute__((always_inline)) void chmax(T& a, const T& b) {a=a<b?b:a;}
  template<typename T>
  __attribute__((always_inline)) void chmin(T& a, const T& b) {a=a<b?a:b;}
  void debug_out() {cerr << endl;}
  template <typename Head, typename... Tail>
  void debug_out(Head H, Tail... T) {
    cerr << " " << std::to_string(H);
    debug_out(T...);
  }
  #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
}
using namespace Template;

struct Segment {
	ll l, r, val;
	Segment(): l{0}, r{0} {}
	Segment(ll a, ll b): l{a}, r{b} {}
};

vector<Segment> segs;

ll n, m;

inline void decompose_into_segments(ll i) {
	ll k = 1;
	while (k <= i) {
		ll first = k;
		ll q = i / k;
		ll second = i / q;
		k = second + 1;
		segs.eb(first, second);
	}
}

Mint get(int l, int r) {
	return Mint(l + r) * (r - l + 1) / 2;
}

int32_t main() {
    #define filename ""
    if (fopen(filename".INP", "r")) {
        freopen(filename".INP", "r", stdin);
        freopen(filename".OUT", "w", stdout);
    }
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    read(n, m);
    decompose_into_segments(n);

    // n*n - [n/1]*1 -[n/2]*2 - ...
    Mint cur = Mint(n)*min(n, m);
    bool quit = false;

    for (auto &p : segs) {
    	int l = p.l, r = p.r, val = n / l;
    	if (r >= m) {
    		r = m;
    		quit = true;
    	}
    	cur -= Mint(val) * get(l, r);
    	if (quit) break;
    }

    if (n < m) {
    	cur += Mint(n) * (m - n);
    }

    write(cur);

    return 0;
}


#define md 1000000007
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define INTEGERONLY
#ifdef IALL
  #define int long long
#endif
namespace Template {
  #define FOR(i, x, y) for(int i = (x); i <= (y); ++i)
  #define FORD(i, x, y) for(int i = (x); i >= (y); --i)
  #define MASK(i) (1LL << (i))
  #define COUNT(x) __builtin_popcountll(x)
  #define BIT(x, i) (((x) >> (i)) & 1)
  #define pb push_back
  #define eb emplace_back
  #define Size(v) (int)v.size()
  typedef long long ll;
  typedef long double ld;
  typedef vector<int> vi;
  typedef vector<long long> vll;
  typedef vector<pair<int, int>> vii;
  typedef pair<int, int> ii;
  template <typename T>
  using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
  const double pi = acos(-1);
  struct Point {
    ll x, y;
    Point(): x{0}, y{0} {}
    Point(ll a, ll b): x{a}, y{b} {}
    bool operator<(const Point& other) const {
      return make_pair(x, y) < make_pair(other.x, other.y);
    }
    Point operator-(const Point& other) const {
      return Point(x - other.x, y - other.y);
    }
    ll operator*(const Point& other) const {
      return (x * other.y - y * other.x);
    }
    ll operator%(const Point& other) const {
      return (x * other.x + y * other.y);
    }
    double len() {
      return sqrt((double)x * x + y * y);
    }
  };
  double angle(const Point & a, const Point & b, const Point & c) {return atan2((a - b) * (c - b), (a - b) % (c - b));}
  double dist(const Point & a, const Point & b) {return (b - a).len();}
  ll area2(const Point & a, const Point & b, const Point & c) {return abs((b - a) * (c - a));}
  bool obtuse(const Point & a, const Point & b, const Point & c) {return abs(angle(a, b, c)) > pi / 2;}
  ll eval(Point a, Point b, Point c) {return (b - a) * (c - b);}
  bool cw(Point a, Point b, Point c) {return eval(a, b, c) < 0;}
  bool ccw(Point a, Point b, Point c) {return eval(a, b, c) > 0;}
  void convex_hull(vector<Point> & a) {
    if (Size(a) == 1) return;
    sort(a.begin(), a.end());
    Point p1 = a[0], p2 = a.back();
    vector<Point> up, down;
    up.push_back(p1);
    down.push_back(p1);
    for (int i = 1; i < Size(a); ++i) {
      if (i == Size(a) - 1 || cw(p1, a[i], p2)) {
        while (Size(up) >= 2 && !cw(up[Size(up) - 2], up[Size(up) - 1], a[i])) {
          up.pop_back();
        }
        up.push_back(a[i]);
      }
      if (i == Size(a) - 1 || ccw(p1, a[i], p2)) {
        while (Size(down) >= 2 && !ccw(down[Size(down) - 2], down[Size(down) - 1], a[i])) {
          down.pop_back();
        }
        down.push_back(a[i]);
      }
    }
    a.clear();
    // convex hull in clockwise order
    for (int i = 0; i < Size(up); ++i) a.pb(up[i]);
    for (int i = Size(down) - 2; i > 0; --i) a.pb(down[i]);
  }
  double area(vector<Point> & temp) {
    int n = Size(temp);
    double res = 0;
    for (int i = 0; i < n - 1; ++i) {
      // actually, this represent the vector with root (0, 0) to point temp
      res += temp[i] * temp[i + 1];
    }
    res += temp[n - 1] * temp[0];
    return abs(res) / 2.0;
  }
  ll raw_dist(const Point& a, const Point& b) {
    return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y);
  }
  template <typename T>
  T inverse(T a, T m) {
    T u = 0, v = 1;
    while (a != 0) {
      T t = m / a;
      m -= t * a; swap(a, m);
      u -= t * v; swap(u, v);
    }
    assert(m == 1);
    return u;
  }
  mt19937 mt_rng(chrono::steady_clock::now().time_since_epoch().count());
  ll randint(ll a, ll b) {
    return uniform_int_distribution<ll>(a, b)(mt_rng);
  }
  template <typename T>
  class Modular {
   public:
    using Type = typename decay<decltype(T::value)>::type;
    constexpr Modular() : value() {}
    template <typename U>
    Modular(const U& x) {
      value = normalize(x);
    }
    template <typename U>
    static Type normalize(const U& x) {
      Type v;
      if (-mod() <= x && x < mod()) v = static_cast<Type>(x);
      else v = static_cast<Type>(x % mod());
      if (v < 0) v += mod();
      return v;
    }
    const Type& operator()() const { return value; }
    template <typename U>
    explicit operator U() const { return static_cast<U>(value); }
    constexpr static Type mod() { return T::value; }
    Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; }
    Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; }
    template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); }
    template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); }
    Modular& operator++() { return *this += 1; }
    Modular& operator--() { return *this -= 1; }
    #ifdef IALL
      #undef int
    #endif
    Modular operator++(int) { Modular result(*this); *this += 1; return result; }
    Modular operator--(int) { Modular result(*this); *this -= 1; return result; }
    Modular operator-() const { return Modular(-value); }
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) {
    #ifdef IALL
      #define int long long
    #endif
  #ifdef _WIN32
      uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
      uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
      asm(
        "divl %4; \n\t"
        : "=a" (d), "=d" (m)
        : "d" (xh), "a" (xl), "r" (mod())
      );
      value = m;
  #else
      value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
  #endif
      return *this;
    }
    #ifdef IALL
      #define int long long
    #endif
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, ll>::value, Modular>::type& operator*=(const Modular& rhs) {
      ll q = static_cast<ll>(static_cast<ld>(value) * rhs.value / mod());
      value = normalize(value * rhs.value - q * mod());
      return *this;
    }
    template <typename U = T>
    typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) {
      value = normalize(value * rhs.value);
      return *this;
    }
    Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); }
    friend const Type& abs(const Modular& x) { return x.value; }
    template <typename U>
    friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename U>
    friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename V, typename U>
    friend V& operator>>(V& stream, Modular<U>& number);
   private:
    Type value;
  };
  template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; }
  template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); }
  template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; }
  template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; }
  template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template<typename T, typename U>
  Modular<T> power(const Modular<T>& a, const U& b) {
    assert(b >= 0);
    Modular<T> x = a, res = 1;
    U p = b;
    while (p > 0) {
      if (p & 1) res *= x;
      x *= x;
      p >>= 1;
    }
    return res;
  }
  template <typename T>
  bool IsZero(const Modular<T>& number) {
    return number() == 0;
  }
  template <typename T>
  string to_string(const Modular<T>& number) {
    return to_string(number());
  }
  template <typename U, typename T>
  U& operator<<(U& stream, const Modular<T>& number) {
    return stream << number();
  }
  template <typename U, typename T>
  U& operator>>(U& stream, Modular<T>& number) {
    typename common_type<typename Modular<T>::Type, ll>::type x;
    stream >> x;
    number.value = Modular<T>::normalize(x);
    return stream;
  }
  using Mint = Modular<std::integral_constant<decay<decltype(md)>::type, md>>;
  inline void set_precision(const int& x) {cout << fixed << setprecision(x);}
  #ifdef INTEGERONLY
    inline void read(Mint & x) {char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=x*10+c-48;if(nega) x=-x;}
    inline void writep(const Mint & _x){int x=(int)_x;if(x>9) writep(x/10);putchar(x%10+48);}
    inline void write(const Mint & _x) {int x=(int)_x;if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    inline void writeln(const Mint & x) {write(x);putchar('\n');}
    inline void sysout(const Mint & x) {cout << x;}
    template <typename T> inline void read(T &x){char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=(x<<3)+(x<<1)+c-48;if(nega) x=-x;}
    template <typename T> inline void writep(const T & x){if(x>9) writep(x/10);putchar(x%10+48);}
    template <typename T> inline void write(T x){if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    template <typename T> inline void writeln(const T & x){write(x);putchar('\n');}
    template<class H, class... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
    }
    template<class H, class... T> inline void write(const H& h, const T&... t) {
      write(h);
      write(t...);
    }
    template<class H, class... T> inline void writeln(const H& h, const T&... t) {
      write(h);
      write(t...);
      putchar('\n');
    }
  #endif
  #ifndef INTEGERONLY
    template<typename T> inline void read(T& x) {cin >> x;}
    template<typename T> inline void write(const T& x) {cout << x << ' ';}
    template<typename T> inline void writeln(const T& x) {cout << x << '\n';}
    template<typename H, typename... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
  }
  template<typename H, typename... T> inline void write(const H& h, const T&... t) {
    write(h);
    write(t...);
  }
  template<typename H, typename... T> inline void writeln(const H& h, const T&... t) {
    write(h);
    write(t...);
    cout << '\n';
  }
  #endif
  template <typename T>
  __attribute__((always_inline)) void chmax(T& a, const T& b) {a=a<b?b:a;}
  template<typename T>
  __attribute__((always_inline)) void chmin(T& a, const T& b) {a=a<b?a:b;}
  void debug_out() {cerr << endl;}
  template <typename Head, typename... Tail>
  void debug_out(Head H, Tail... T) {
    cerr << " " << std::to_string(H);
    debug_out(T...);
  }
  #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
}
using namespace Template;

struct Segment {
	ll l, r, val;
	Segment(): l{0}, r{0}, val{0} {}
	Segment(ll a, ll b, ll c): l{a}, r{b}, val{c} {}
};

vector<Segment> segs;

ll n, m;

inline void decompose_into_segments(ll i) {
	ll k = 1;
	while (k <= i) {
		ll first = k;
		ll q = i / k;
		ll second = i / q;
		k = second + 1;
		segs.eb(first, second, q);
	}
}

Mint get(int l, int r) {
	return Mint(l + r) * (r - l + 1) / 2;
}

int32_t main() {
    #define filename ""
    if (fopen(filename".INP", "r")) {
        freopen(filename".INP", "r", stdin);
        freopen(filename".OUT", "w", stdout);
    }
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    read(n, m);
    decompose_into_segments(n);

    // n*n - [n/1]*1 -[n/2]*2 - ...
    Mint cur = Mint(n)*min(n, m);
    bool quit = false;

    for (auto &p : segs) {
    	int l = p.l, r = p.r, val = p.val;
    	if (r >= m) {
    		r = m;
    		quit = true;
    	}
    	cur -= Mint(val) * get(l, r);
    	if (quit) break;
    }

    if (n < m) {
    	cur += Mint(n) * (m - n);
    }

    write(cur);

    return 0;
}


#define md 1000000007
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define IALL
#define INTEGERONLY
#ifdef IALL
  #define int long long
#endif
namespace Template {
  #define FOR(i, x, y) for(int i = (x); i <= (y); ++i)
  #define FORD(i, x, y) for(int i = (x); i >= (y); --i)
  #define MASK(i) (1LL << (i))
  #define COUNT(x) __builtin_popcountll(x)
  #define BIT(x, i) (((x) >> (i)) & 1)
  #define pb push_back
  #define eb emplace_back
  #define Size(v) (int)v.size()
  typedef long long ll;
  typedef long double ld;
  typedef vector<int> vi;
  typedef vector<long long> vll;
  typedef vector<pair<int, int>> vii;
  typedef pair<int, int> ii;
  template <typename T>
  using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
  const double pi = acos(-1);
  struct Point {
    ll x, y;
    Point(): x{0}, y{0} {}
    Point(ll a, ll b): x{a}, y{b} {}
    bool operator<(const Point& other) const {
      return make_pair(x, y) < make_pair(other.x, other.y);
    }
    Point operator-(const Point& other) const {
      return Point(x - other.x, y - other.y);
    }
    ll operator*(const Point& other) const {
      return (x * other.y - y * other.x);
    }
    ll operator%(const Point& other) const {
      return (x * other.x + y * other.y);
    }
    double len() {
      return sqrt((double)x * x + y * y);
    }
  };
  double angle(const Point & a, const Point & b, const Point & c) {return atan2((a - b) * (c - b), (a - b) % (c - b));}
  double dist(const Point & a, const Point & b) {return (b - a).len();}
  ll area2(const Point & a, const Point & b, const Point & c) {return abs((b - a) * (c - a));}
  bool obtuse(const Point & a, const Point & b, const Point & c) {return abs(angle(a, b, c)) > pi / 2;}
  ll eval(Point a, Point b, Point c) {return (b - a) * (c - b);}
  bool cw(Point a, Point b, Point c) {return eval(a, b, c) < 0;}
  bool ccw(Point a, Point b, Point c) {return eval(a, b, c) > 0;}
  void convex_hull(vector<Point> & a) {
    if (Size(a) == 1) return;
    sort(a.begin(), a.end());
    Point p1 = a[0], p2 = a.back();
    vector<Point> up, down;
    up.push_back(p1);
    down.push_back(p1);
    for (int i = 1; i < Size(a); ++i) {
      if (i == Size(a) - 1 || cw(p1, a[i], p2)) {
        while (Size(up) >= 2 && !cw(up[Size(up) - 2], up[Size(up) - 1], a[i])) {
          up.pop_back();
        }
        up.push_back(a[i]);
      }
      if (i == Size(a) - 1 || ccw(p1, a[i], p2)) {
        while (Size(down) >= 2 && !ccw(down[Size(down) - 2], down[Size(down) - 1], a[i])) {
          down.pop_back();
        }
        down.push_back(a[i]);
      }
    }
    a.clear();
    // convex hull in clockwise order
    for (int i = 0; i < Size(up); ++i) a.pb(up[i]);
    for (int i = Size(down) - 2; i > 0; --i) a.pb(down[i]);
  }
  double area(vector<Point> & temp) {
    int n = Size(temp);
    double res = 0;
    for (int i = 0; i < n - 1; ++i) {
      // actually, this represent the vector with root (0, 0) to point temp
      res += temp[i] * temp[i + 1];
    }
    res += temp[n - 1] * temp[0];
    return abs(res) / 2.0;
  }
  ll raw_dist(const Point& a, const Point& b) {
    return (b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y);
  }
  template <typename T>
  T inverse(T a, T m) {
    T u = 0, v = 1;
    while (a != 0) {
      T t = m / a;
      m -= t * a; swap(a, m);
      u -= t * v; swap(u, v);
    }
    assert(m == 1);
    return u;
  }
  mt19937 mt_rng(chrono::steady_clock::now().time_since_epoch().count());
  ll randint(ll a, ll b) {
    return uniform_int_distribution<ll>(a, b)(mt_rng);
  }
  template <typename T>
  class Modular {
   public:
    using Type = typename decay<decltype(T::value)>::type;
    constexpr Modular() : value() {}
    template <typename U>
    Modular(const U& x) {
      value = normalize(x);
    }
    template <typename U>
    static Type normalize(const U& x) {
      Type v;
      if (-mod() <= x && x < mod()) v = static_cast<Type>(x);
      else v = static_cast<Type>(x % mod());
      if (v < 0) v += mod();
      return v;
    }
    const Type& operator()() const { return value; }
    template <typename U>
    explicit operator U() const { return static_cast<U>(value); }
    constexpr static Type mod() { return T::value; }
    Modular& operator+=(const Modular& other) { if ((value += other.value) >= mod()) value -= mod(); return *this; }
    Modular& operator-=(const Modular& other) { if ((value -= other.value) < 0) value += mod(); return *this; }
    template <typename U> Modular& operator+=(const U& other) { return *this += Modular(other); }
    template <typename U> Modular& operator-=(const U& other) { return *this -= Modular(other); }
    Modular& operator++() { return *this += 1; }
    Modular& operator--() { return *this -= 1; }
    #ifdef IALL
      #undef int
    #endif
    Modular operator++(int) { Modular result(*this); *this += 1; return result; }
    Modular operator--(int) { Modular result(*this); *this -= 1; return result; }
    Modular operator-() const { return Modular(-value); }
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, int>::value, Modular>::type& operator*=(const Modular& rhs) {
    #ifdef IALL
      #define int long long
    #endif
  #ifdef _WIN32
      uint64_t x = static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value);
      uint32_t xh = static_cast<uint32_t>(x >> 32), xl = static_cast<uint32_t>(x), d, m;
      asm(
        "divl %4; \n\t"
        : "=a" (d), "=d" (m)
        : "d" (xh), "a" (xl), "r" (mod())
      );
      value = m;
  #else
      value = normalize(static_cast<int64_t>(value) * static_cast<int64_t>(rhs.value));
  #endif
      return *this;
    }
    #ifdef IALL
      #define int long long
    #endif
    template <typename U = T>
    typename enable_if<is_same<typename Modular<U>::Type, ll>::value, Modular>::type& operator*=(const Modular& rhs) {
      ll q = static_cast<ll>(static_cast<ld>(value) * rhs.value / mod());
      value = normalize(value * rhs.value - q * mod());
      return *this;
    }
    template <typename U = T>
    typename enable_if<!is_integral<typename Modular<U>::Type>::value, Modular>::type& operator*=(const Modular& rhs) {
      value = normalize(value * rhs.value);
      return *this;
    }
    Modular& operator/=(const Modular& other) { return *this *= Modular(inverse(other.value, mod())); }
    friend const Type& abs(const Modular& x) { return x.value; }
    template <typename U>
    friend bool operator==(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename U>
    friend bool operator<(const Modular<U>& lhs, const Modular<U>& rhs);
    template <typename V, typename U>
    friend V& operator>>(V& stream, Modular<U>& number);
   private:
    Type value;
  };
  template <typename T> bool operator==(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value == rhs.value; }
  template <typename T, typename U> bool operator==(const Modular<T>& lhs, U rhs) { return lhs == Modular<T>(rhs); }
  template <typename T, typename U> bool operator==(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) == rhs; }
  template <typename T> bool operator!=(const Modular<T>& lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(const Modular<T>& lhs, U rhs) { return !(lhs == rhs); }
  template <typename T, typename U> bool operator!=(U lhs, const Modular<T>& rhs) { return !(lhs == rhs); }
  template <typename T> bool operator<(const Modular<T>& lhs, const Modular<T>& rhs) { return lhs.value < rhs.value; }
  template <typename T> Modular<T> operator+(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T, typename U> Modular<T> operator+(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) += rhs; }
  template <typename T> Modular<T> operator-(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T, typename U> Modular<T> operator-(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) -= rhs; }
  template <typename T> Modular<T> operator*(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T, typename U> Modular<T> operator*(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) *= rhs; }
  template <typename T> Modular<T> operator/(const Modular<T>& lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(const Modular<T>& lhs, U rhs) { return Modular<T>(lhs) /= rhs; }
  template <typename T, typename U> Modular<T> operator/(U lhs, const Modular<T>& rhs) { return Modular<T>(lhs) /= rhs; }
  template<typename T, typename U>
  Modular<T> power(const Modular<T>& a, const U& b) {
    assert(b >= 0);
    Modular<T> x = a, res = 1;
    U p = b;
    while (p > 0) {
      if (p & 1) res *= x;
      x *= x;
      p >>= 1;
    }
    return res;
  }
  template <typename T>
  bool IsZero(const Modular<T>& number) {
    return number() == 0;
  }
  template <typename T>
  string to_string(const Modular<T>& number) {
    return to_string(number());
  }
  template <typename U, typename T>
  U& operator<<(U& stream, const Modular<T>& number) {
    return stream << number();
  }
  template <typename U, typename T>
  U& operator>>(U& stream, Modular<T>& number) {
    typename common_type<typename Modular<T>::Type, ll>::type x;
    stream >> x;
    number.value = Modular<T>::normalize(x);
    return stream;
  }
  using Mint = Modular<std::integral_constant<decay<decltype(md)>::type, md>>;
  inline void set_precision(const int& x) {cout << fixed << setprecision(x);}
  #ifdef INTEGERONLY
    inline void read(Mint & x) {char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=x*10+c-48;if(nega) x=-x;}
    inline void writep(const Mint & _x){int x=(int)_x;if(x>9) writep(x/10);putchar(x%10+48);}
    inline void write(const Mint & _x) {int x=(int)_x;if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    inline void writeln(const Mint & x) {write(x);putchar('\n');}
    inline void sysout(const Mint & x) {cout << x;}
    template <typename T> inline void read(T &x){char c;bool nega=0;while((!isdigit(c=getchar()))&&(c!='-'));if(c=='-'){nega=1;c=getchar();}x=c-48;while(isdigit(c=getchar())) x=(x<<3)+(x<<1)+c-48;if(nega) x=-x;}
    template <typename T> inline void writep(const T & x){if(x>9) writep(x/10);putchar(x%10+48);}
    template <typename T> inline void write(T x){if(x<0){putchar('-');x=-x;}writep(x);putchar(' ');}
    template <typename T> inline void writeln(const T & x){write(x);putchar('\n');}
    template<class H, class... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
    }
    template<class H, class... T> inline void write(const H& h, const T&... t) {
      write(h);
      write(t...);
    }
    template<class H, class... T> inline void writeln(const H& h, const T&... t) {
      write(h);
      write(t...);
      putchar('\n');
    }
  #endif
  #ifndef INTEGERONLY
    template<typename T> inline void read(T& x) {cin >> x;}
    template<typename T> inline void write(const T& x) {cout << x << ' ';}
    template<typename T> inline void writeln(const T& x) {cout << x << '\n';}
    template<typename H, typename... T> inline void read(H& h, T&... t) {
      read(h);
      read(t...);
  }
  template<typename H, typename... T> inline void write(const H& h, const T&... t) {
    write(h);
    write(t...);
  }
  template<typename H, typename... T> inline void writeln(const H& h, const T&... t) {
    write(h);
    write(t...);
    cout << '\n';
  }
  #endif
  template <typename T>
  __attribute__((always_inline)) void chmax(T& a, const T& b) {a=a<b?b:a;}
  template<typename T>
  __attribute__((always_inline)) void chmin(T& a, const T& b) {a=a<b?a:b;}
  void debug_out() {cerr << endl;}
  template <typename Head, typename... Tail>
  void debug_out(Head H, Tail... T) {
    cerr << " " << std::to_string(H);
    debug_out(T...);
  }
  #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
}
using namespace Template;

struct Segment {
	ll l, r, val;
	Segment(): l{0}, r{0}, val{0} {}
	Segment(ll a, ll b, ll c): l{a}, r{b}, val{c} {}
};

vector<Segment> segs;

ll n, m;

inline void decompose_into_segments(ll i) {
	ll k = 1;
	while (k <= i) {
		ll first = k;
		ll q = i / k;
		ll second = i / q;
		k = second + 1;
		segs.eb(first, second, q);
	}
}

Mint get(int l, int r) {
	return Mint(l + r) * (r - l + 1) / 2;
}

int32_t main() {
    #define filename ""
    if (fopen(filename".INP", "r")) {
        freopen(filename".INP", "r", stdin);
        freopen(filename".OUT", "w", stdout);
    }
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    read(n, m);
    decompose_into_segments(n);

    // n*n - [n/1]*1 -[n/2]*2 - ...
    Mint cur = Mint(n)*min(n, m);
    bool quit = false;

    for (auto &p : segs) {
    	int l = p.l, r = p.r, val = p.val;
    	if (r >= m) {
    		r = m;
    		quit = true;
    	}
    	cur -= Mint(val) * get(l, r);
    	if (quit) break;
    }

    if (n < m) {
    	cur += Mint(n) * (m - n);
    }

    write(cur);

    return 0;
}


#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
using namespace std;

long long n,m;
long long mod=1000000007;
inline long long saam(long long s,long long e,long long n){
	s%=mod*2;
	e%=mod*2;
	n%=mod*2;
	return (((s+e)*n)%(2*mod))/2;
}

int main(){
	cin.sync_with_stdio(false);
	cout.sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	long long _m=m;
	int s=1;
	long long sol=0;
	if(m>n){
		sol= ((((m%mod)-(n%mod ) ) * (n%mod))%mod+mod)%mod;
		m=n;
	}
	while(n/s >m){
		s++;
	}
	s--;
	long long curr=m;
	for(;s<=3200000 && curr!=0;s++){
		sol+= saam(n%curr,n%(n/(s+1) +1),curr-n/(s+1));
		curr=n/(s+1);
		if(sol>mod)sol-=mod;
	}
	for(;curr>0;curr--){
		sol+= n%curr;
	}
	sol%=mod;
	cout<<sol<<endl;
}


#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
using namespace std;

long long n,m;
long long mod=1000000007;
long long saam(long long s,long long e,long long n){
	s%=mod*2;
	e%=mod*2;
	n%=mod*2;
	return (((s+e)*n)%(2*mod))/2;
}

int main(){
	cin.sync_with_stdio(false);
	cout.sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	long long _m=m;
	int s=1;
	long long sol=0;
	if(m>n){
		sol= ((((m%mod)-(n%mod ) ) * (n%mod))%mod+mod)%mod;
		m=n;
	}
	while(n/s >m){
		s++;
	}
	s--;
	long long curr=m;
	for(;s<=3200000 && curr!=0;s++){
		sol+= saam(n%curr,n%(n/(s+1) +1),curr-n/(s+1));
		curr=n/(s+1);
		if(sol>mod)sol-=mod;
	}
	for(;curr>0;curr--){
		sol+= n%curr;
		sol%=mod;
	}
	cout<<sol<<endl;

	long long sol2=0;
	for(int i=1;i<=_m;i++){
		sol2+= n%i;

	}
	cout<<sol2%mod<<endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define fi first
#define se second
#define UP(a,b,c) for(ll (a)=(b);(a)<(c);(a)++)
#define UU(a,b,c) for(ll (a)=(b);(a)<=(c);(a)++)
#define DN(a,b,c) for(ll (a)=(b);(a)>(c);(a)--)
#define DU(a,b,c) for(ll (a)=(b);(a)>=(c);(a)--)

int n, zero = -1, one = -1, a, b, cnt = 0, before;
string str;

void reset()
{
}

void input()
{
	cin>>n;
	UU(i,1,n) str += '0';
}

ll binser(int l, int r, int need)
{
	if(l == r)
	{
		return l;
	}
	if(l <= r)
	{
		int m = l+r>>1, temp, changed = 0;

		UU(i,m + 1, r)
		{
			changed++;
			if(cnt % 2)
			{
				str[i] = (need == 1 ? '1' : '0');
			}
			else
			{
				str[i] = (need == 1 ? '0' : '1');
			}
		}
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>temp;

		if((cnt % 2 && before - temp != changed) ||(cnt%2 == 0 && temp - before != changed))
		{
			before = temp;
			return binser(m + 1, r, need);
		}
		else
		{
			before = temp;
			return binser(l, m, need);
		}
	}
}

void solve()
{
	cout<<"? "<<str<<endl;
	cnt++;
	cin>>a;
	str[0] = '1';
	cout<<"? "<<str<<endl;
	cnt++;
	cin>>b;
	if(a > b)
	{
		one = 0;
		UP(i,0,n) str[i] = '1';
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>before;
		zero = binser(0, n - 1, 0);
	}
	else
	{
		zero = 0;
		UP(i,0,n) str[i] = '0';
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>before;
		one = binser(0, n - 1, 1);
	}
	cout<<"! "<<zero + 1<<" "<<one + 1<<endl;
}

void LetsRock()
{
	solve();
}

int main()
{
	ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

		input();
		reset();
		LetsRock();

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define fi first
#define se second
#define UP(a,b,c) for(ll (a)=(b);(a)<(c);(a)++)
#define UU(a,b,c) for(ll (a)=(b);(a)<=(c);(a)++)
#define DN(a,b,c) for(ll (a)=(b);(a)>(c);(a)--)
#define DU(a,b,c) for(ll (a)=(b);(a)>=(c);(a)--)

int n, zero = -1, one = -1, a, b, cnt = 0, before;
string str;

void reset()
{
}

void input()
{
	cin>>n;
	UU(i,1,n) str += '0';
}

ll binser(int l, int r, int need)
{
	if(l == r)
	{
		return l;
	}
	if(l <= r)
	{
		int m = l+r>>1, temp, changed = 0;

		UP(i,m + 1, r)
		{
			changed++;
			if(cnt % 2)
			{
				(need == 1 ? '0' : '1');
			}
			else
			{
				(need == 1 ? '1' : '0');
			}
		}

		cout<<"? "<<str<<endl;
		cnt++;
		cin>>temp;

		if((cnt % 2 && before - temp != changed) ||(cnt%2 == 0 && temp - before != changed))
		{
			before = temp;
			return binser(m + 1, r, need);
		}
		else
		{
			before = temp;
			return binser(l, m, need);
		}
	}
}

void solve()
{
	cout<<"? "<<str<<endl;
	cnt++;
	cin>>a;
	str[0] = '1';
	cout<<"? "<<str<<endl;
	cnt++;
	cin>>b;
	if(a > b)
	{
		one = 0;
		UP(i,0,n) str[i] = '1';
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>before;
		zero = binser(0, n - 1, 0);
	}
	else
	{
		zero = 0;
		UP(i,0,n) str[i] = '0';
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>before;
		one = binser(0, n - 1, 1);
	}
	cout<<"! "<<zero<<" "<<one<<endl;
}

void LetsRock()
{
	solve();
}

int main()
{
	ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

		input();
		reset();
		LetsRock();

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define fi first
#define se second
#define UP(a,b,c) for(ll (a)=(b);(a)<(c);(a)++)
#define UU(a,b,c) for(ll (a)=(b);(a)<=(c);(a)++)
#define DN(a,b,c) for(ll (a)=(b);(a)>(c);(a)--)
#define DU(a,b,c) for(ll (a)=(b);(a)>=(c);(a)--)

int n, zero = -1, one = -1, a, b, cnt = 0, before;
string str;

void reset()
{
}

void input()
{
	cin>>n;
	UU(i,1,n) str += '0';
}

ll binser(int l, int r, int need)
{
	if(l == r)
	{
		return l;
	}
	if(l <= r)
	{
		int m = l+r>>1, temp, changed = 0;

		UP(i,m + 1, r)
		{
			changed++;
			if(cnt % 2)
			{
				(need == 1 ? '0' : '1');
			}
			else
			{
				(need == 1 ? '1' : '0');
			}
		}

		cout<<"? "<<str<<endl;
		cnt++;
		cin>>temp;

		if((cnt % 2 && before - temp != changed) ||(cnt%2 == 0 && temp - before != changed))
		{
			before = temp;
			return binser(m + 1, r, need);
		}
		else
		{
			before = temp;
			return binser(l, m, need);
		}
	}
}

void solve()
{
	cout<<"? "<<str<<endl;
	cnt++;
	cin>>a;
	str[0] = '1';
	cout<<"? "<<str<<endl;
	cnt++;
	cin>>b;
	if(a > b)
	{
		one = 0;
		UP(i,0,n) str[i] = '1';
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>before;
		zero = binser(0, n - 1, 0);
	}
	else
	{
		zero = 0;
		UP(i,0,n) str[i] = '0';
		cout<<"? "<<str<<endl;
		cnt++;
		cin>>before;
		one = binser(0, n - 1, 1);
	}
	cout<<"! "<<zero + 1<<" "<<one + 1<<endl;
}

void LetsRock()
{
	solve();
}

int main()
{
	ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

		input();
		reset();
		LetsRock();

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;

int n;

int ask(string s) {
  cout<<"? ";
  cout<<s<<endl;
  cout.flush();
  int ham; cin>>ham;
  return ham;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  cin>>n;
  int ans0=-1, ans1=-1;
  bool done = false;
  while (!done) {
    string buf = string(n, '0');
    int res0 = ask(buf);
    buf[0] = '1';
    int res1 = ask(buf);
    int x=-1;
    if (res1 < res0) {
      ans1=0; x=0;
    } else {
      ans0=0; x=1;
    }

    if (n == 2) {
      if (res1 < res0) {
	ans1=0; ans0=1;
      } else {
	ans0=0; ans1=1;
      }
      break;
    }

    int l = 1; int r = n;
    while (r - l > 1) {
      //cout<<l<<" "<<r<<endl;
      int mid = (l + r)/2;
      for (int k=l; k<mid; k++) buf[k] = '0';
      int res0 = ask(buf);
      for (int k=l; k<mid; k++) buf[k] = '1';
      int res1 = ask(buf);

      if (r - l == 2) {
	if (x==0) {
	  if (res1<res0) ans0=r; else ans0=l;
	} else {
	  if (res1<res0) ans1=l; else ans1=r;
	}
	done = true;
	break;
      }

      // increased by length, so all 0's
      if (res1-res0 == mid-l) {
	if (x == 0) {
	  done=true;
	  ans0 = l;
	  break;
	} else {
	  l = mid;
	}

	// decreased by length, so all 1's
      } else if (res0-res1 == mid-l) {
	if (x == 1) {
	  done=true;
	  ans1 = l;
	  break;
	} else {
	  l = mid;
	}
      } else {
	r = mid;
      }
    }
    assert(done);
  }

  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;

int n;

int ask(string s) {
  cout<<"? ";
  cout<<s<<endl;
  cout.flush();
  int ham; cin>>ham;
  return ham;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  cin>>n;
  int ans0=-1, ans1=-1;
  bool done = false;
  while (!done) {
    string buf = string(n, '0');
    int res0 = ask(buf);
    buf[0] = '1';
    int res1 = ask(buf);
    int x=-1;
    if (res1 < res0) {
      ans1=0; x=0;
    } else {
      ans0=0; x=1;
    }

    int l = 1; int r = n;
    while (r - l > 1) {
      int mid = (l + r)/2;
      for (int k=l; k<mid; k++) buf[k] = '0';
      int res0 = ask(buf);
      for (int k=l; k<mid; k++) buf[k] = '1';
      int res1 = ask(buf);

      if (res1-res0 == mid-l) {
	if (x == 0) {
	  done=true;
	  ans0 = l;
	  break;
	} else {
	  l = mid;
	}
      } else if (res0-res1 == mid-l) {
	if (x == 1) {
	  done=true;
	  ans1 = l;
	  break;
	} else {
	  l = mid;
	}
      } else {
	r = mid;
      }
    }
  }

  cout<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;

int n;

int ask(string s) {
  cout<<"? ";
  cout<<s<<endl;
  cout.flush();
  int ham; cin>>ham;
  return ham;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  cin>>n;
  int ans0=-1, ans1=-1;
  bool done = false;
  while (!done) {
    string buf = string(n, '0');
    int res0 = ask(buf);
    buf[0] = '1';
    int res1 = ask(buf);
    int x=-1;
    if (res1 < res0) {
      ans1=0; x=0;
    } else {
      ans0=0; x=1;
    }

    int l = 1; int r = n;
    while (r - l > 1) {
      int mid = (l + r)/2;
      for (int k=l; k<mid; k++) buf[k] = '0';
      int res0 = ask(buf);
      for (int k=l; k<mid; k++) buf[k] = '1';
      int res1 = ask(buf);

      if (res1-res0 == mid-l) {
	if (x == 0) {
	  done=true;
	  ans0 = l;
	  break;
	} else {
	  l = mid;
	}
      } else if (res0-res1 == mid-l) {
	if (x == 1) {
	  done=true;
	  ans1 = l;
	  break;
	} else {
	  l = mid;
	}
      } else {
	r = mid;
      }
    }
  }

  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;
int res0, res1;

int ask(string s) {
  cout<<"? "<<s<<endl;
  cout.flush();
  int x; cin>>x;
  return x;
}

int ans0 = -1;
int ans1 = -1;

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  int n; cin>>n;

  string buf(n, '0');
  res0 = ask(buf);
  buf.front() = '1';
  res1 = ask(buf);

  if (res1<res0) {
    ans1 = 0;
  } else {
    ans0 = 0;
  }

  int lo = 1;
  int hi = n;

  while (hi - lo > 1) {
    int mid = (hi + lo) / 2;

    // [lo, mid)
    string buf(n, '1');
    for (int i=lo; i<mid; i++) {
      buf[i] = '0';
    }
    int res = ask(buf);

    int len = mid - lo;

    if (ans0 == -1) {
      int diff = res - res1; //ones-zeros
      if (diff!=len) {
	hi = mid;
      } else {
	lo = mid;
      }
    } else if (ans1 == -1) {
      int diff = res1 - res; //zeros-ones
      if (diff!=len) {
	hi = mid;
      } else {
	lo = mid;
      }
    }
  }

  if (ans1==-1) ans1=lo; else ans0=lo;
  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;

int n;

int ask(string s) {
  cout<<"? ";
  cout<<s<<endl;
  cout.flush();
  int ham; cin>>ham;
  return ham;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  cin>>n;
  int ans0=-1, ans1=-1;
  bool done = false;
  while (!done) {
    string buf = string(n, '0');
    int res0 = ask(buf);
    buf[0] = '1';
    int res1 = ask(buf);
    int x=-1;
    if (res1 < res0) {
      ans1=0; x=0;
    } else {
      ans0=0; x=1;
    }

    int l = 1; int r = n;
    while (r - l > 1) {
      //cout<<l<<" "<<r<<endl;
      if (l+1 == r) {
	if (x==0) ans0=l; else ans1=l;
	break;
      }
      int mid = (l + r)/2;
      for (int k=l; k<mid; k++) buf[k] = '0';
      int res0 = ask(buf);
      for (int k=l; k<mid; k++) buf[k] = '1';
      int res1 = ask(buf);

      if (res1-res0 == mid-l) {
	if (x == 0) {
	  done=true;
	  ans0 = l;
	  break;
	} else {
	  l = mid;
	}
      } else if (res0-res1 == mid-l) {
	if (x == 1) {
	  done=true;
	  ans1 = l;
	  break;
	} else {
	  l = mid;
	}
      } else {
	r = mid;
      }
    }
  }

  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;
int res0, res1;

int ask(string s) {
  cout<<"? "<<s<<endl;
  cout.flush();
  int x; cin>>x;
  return x;
}

int ans0 = -1;
int ans1 = -1;

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  int n; cin>>n;

  string buf(n, '0');
  res0 = ask(buf);
  buf.front() = '1';
  res1 = ask(buf);

  if (res1<res0) {
    ans1 = 0;
  } else {
    ans0 = 0;
  }

  int lo = 1;
  int hi = n;

  while (hi - lo > 1) {
    int mid = (hi + lo) / 2;

    // [lo, mid)
    string buf(n, '0');
    for (int i=lo; i<mid; i++) {
      buf[i] = '1';
    }
    int res = ask(buf);

    int len = mid - lo;

    if (ans0 == -1) {
      int diff = res0 - res; //ones-zeros
      if (diff!=len) {
	hi = mid;
      } else {
	lo = mid;
      }
    } else if (ans1 == -1) {
      int diff = res - res0; //zeros-ones
      if (diff!=len) {
	hi = mid;
      } else {
	lo = mid;
      }
    }
  }

  if (ans1==-1) ans1=lo; else ans0=lo;
  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;
int res0, res1;

int ask(string s) {
  cout<<s<<endl;
  cout.flush();
  int x; cin>>x;
  return x;
}

int ans0 = -1;
int ans1 = -1;

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  int n; cin>>n;

  string buf(n, '0');
  res0 = ask(buf);
  buf.front() = '1';
  res1 = ask(buf);

  if (res1<res0) {
    ans1 = 0;
  } else {
    ans0 = 0;
  }

  int lo = 1;
  int hi = n;

  while (hi - lo > 1) {
    int mid = (hi + lo) / 2;

    // [lo, mid)
    string buf(n, '1');
    for (int i=lo; i<mid; i++) {
      buf[i] = '0';
    }
    int res = ask(buf);

    int len = mid - lo;

    if (ans0 == -1) {
      int diff = res - res1; //ones-zeros
      if (diff!=len) {
	hi = mid;
      } else {
	lo = mid;
      }
    } else if (ans1 == -1) {
      int diff = res1 - res; //zeros-ones
      if (diff!=len) {
	hi = mid;
      } else {
	lo = mid;
      }
    }
  }

  if (ans1==-1) ans1=lo; else ans0=lo;
  cout<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;

int n;

int ask(string s) {
  cout<<"? ";
  cout<<s<<endl;
  cout.flush();
  int ham; cin>>ham;
  return ham;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  cin>>n;
  int ans0=-1, ans1=-1;
  bool done = false;
  while (!done) {
    string buf = string(n, '0');
    int res0 = ask(buf);
    buf[0] = '1';
    int res1 = ask(buf);
    int x=-1;
    if (res1 < res0) {
      ans1=0; x=0;
    } else {
      ans0=0; x=1;
    }

    int l = 1; int r = n;
    while (r - l > 1) {
      //cout<<l<<" "<<r<<endl;
      int mid = (l + r)/2;
      for (int k=l; k<mid; k++) buf[k] = '0';
      int res0 = ask(buf);
      for (int k=l; k<mid; k++) buf[k] = '1';
      int res1 = ask(buf);

      if (r - l == 2) {
	if (x==0) {
	  if (res1<res0) ans0=r; else ans0=l;
	} else {
	  if (res1<res0) ans1=l; else ans1=r;
	}
	done = true;
	break;
      }

      // increased by length, so all 0's
      if (res1-res0 == mid-l) {
	if (x == 0) {
	  done=true;
	  ans0 = l;
	  break;
	} else {
	  l = mid;
	}

	// decreased by length, so all 1's
      } else if (res0-res1 == mid-l) {
	if (x == 1) {
	  done=true;
	  ans1 = l;
	  break;
	} else {
	  l = mid;
	}
      } else {
	r = mid;
      }
    }
    assert(done);
  }

  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<typename T>
void out(T x) { cout << x << endl; exit(0); }
#define watch(x) cout << (#x) << " is " << (x) << endl

const int maxn = 1e6 + 5;

int n;

int ask(string s) {
  cout<<"? ";
  cout<<s<<endl;
  cout.flush();
  int ham; cin>>ham;
  return ham;
}

int main() {
  ios_base::sync_with_stdio(false); cin.tie(0);  cout.tie(0);

  cin>>n;
  int ans0=-1, ans1=-1;
  bool done = false;
  while (!done) {
    string buf = string(n, '0');
    int res0 = ask(buf);
    buf[0] = '1';
    int res1 = ask(buf);
    int x=-1;
    if (res1 < res0) {
      ans1=0; x=0;
    } else {
      ans0=0; x=1;
    }

    int l = 1; int r = n;
    while (r - l > 1) {
      //cout<<l<<" "<<r<<endl;
      int mid = (l + r)/2;
      for (int k=l; k<mid; k++) buf[k] = '0';
      int res0 = ask(buf);
      for (int k=l; k<mid; k++) buf[k] = '1';
      int res1 = ask(buf);

      if (res1-res0 == mid-l) {
	if (x == 0) {
	  done=true;
	  ans0 = l;
	  break;
	} else {
	  l = mid;
	}
      } else if (res0-res1 == mid-l) {
	if (x == 1) {
	  done=true;
	  ans1 = l;
	  break;
	} else {
	  l = mid;
	}
      } else {
	r = mid;
      }
    }
    assert(done);
  }

  cout<<"! "<<ans0+1<<" "<<ans1+1<<endl;
  return 0;
}
// don't forget to read in the input :^)


 //Dragon_warrior7(IITK)
#pragma GCC optimize("O0")
#pragma GCC optimize ("Ofast")
#pragma GCC target ("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize ("-ffloat-store")
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define nl cout << '\n'
#define sor(x) sort(x.begin(), x.end())
#define rev(v) reverse(v.begin(), v.end())
#define lb(v, temp) lower_bound(v.begin(), v.end(), temp)
#define ub(v, temp) upper_bound(v.begin(), v.end(), temp)
#define fi first
#define se second
#define inf 1000000000000000000
#define pll pair<ll, ll>
#define vll vector<ll>
#define rub cerr << "\n------------------------------------\n"
#define deb(x) cerr<<#x<<' '<<'='<<' '<<x<<'\n'
#define Lets_be_precise cout<<fixed<<setprecision(10)
ll n,m,a,b,c,k,temp,x,y;
const int MAXN=100000+11;
inline void read(vector<ll> &v);
inline ll max(ll a,ll b);
inline ll min(ll a,ll b);
inline ll gcd(ll a ,ll b);
//#define cerr if(false)cerr
void solveforthiscase(const int & test)
{
cin>>n;
vector<char> v(n,'0');
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
v[0]='1';
int val1,val2;
cin>>val1;
cout<<'?';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
cin>>val2;
int ans0=-1;
int ans1=-1;
if(val2<val1)
ans1=1;
else
ans0=1;
if(ans0==1)
{
    int l=1;
    int r=n;
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'1';
        for(int i=mid;i<n;i++)
        cout<<'0';
        fflush(stdout);
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans1=l;
}
else
{
    int l=1;
    int r=n;
    int mid;
    cout<<'?'<<' ';
    for(int i=0;i<n;i++)
    cout<<'1';
    cout<<endl;
    cin>>val1;
     while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'0';
        for(int i=mid;i<n;i++)
        cout<<'1';
        cout<<endl;
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans0=l;
}
cout<<'!'<<' '<<ans0<<' '<<ans1<<endl;
return ;
}
int main()
{
    ios_base::sync_with_stdio(false);
    Lets_be_precise;
    cin.tie(NULL);
    cout.tie(NULL);
    // #ifndef ONLINE_JUDGE
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    //#endif
    clock_t start, end;
    start = clock();
    int test=1;
    //cin>>test;
    for(int i=1;i<=test;i++)
    {
        solveforthiscase(i);
    }
     end = clock();
    long double time_taken = (long double)(end - start) /(long double)(CLOCKS_PER_SEC);
    cerr << "Time taken by program is : "<< (long double)time_taken*1000<< " milisec ";
}
inline ll max(ll a,ll b)
{return ((a>b)?a:b);}
inline ll min(ll a,ll b)
{return ((a>b)?b:a);}
inline ll gcd(ll a ,ll b)
{if(b==0) return a;a%=b;return gcd(b,a);}
inline void read(vector<ll> &v)
{for (int i = 0; i < v.size(); i++)cin>>v[i];}


 //Dragon_warrior7(IITK)
#pragma GCC optimize("O0")
#pragma GCC optimize ("Ofast")
#pragma GCC target ("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize ("-ffloat-store")
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define nl cout << '\n'
#define sor(x) sort(x.begin(), x.end())
#define rev(v) reverse(v.begin(), v.end())
#define lb(v, temp) lower_bound(v.begin(), v.end(), temp)
#define ub(v, temp) upper_bound(v.begin(), v.end(), temp)
#define fi first
#define se second
#define inf 1000000000000000000
#define pll pair<ll, ll>
#define vll vector<ll>
#define rub cerr << "\n------------------------------------\n"
#define deb(x) cerr<<#x<<' '<<'='<<' '<<x<<'\n'
#define Lets_be_precise cout<<fixed<<setprecision(10)
ll n,m,a,b,c,k,temp,x,y;
const int MAXN=100000+11;
inline void read(vector<ll> &v);
inline ll max(ll a,ll b);
inline ll min(ll a,ll b);
inline ll gcd(ll a ,ll b);
//#define cerr if(false)cerr
void solveforthiscase(const int & test)
{
cin>>n;
vector<char> v(n,'0');
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
v[0]='1';
int val1,val2;
cin>>val1;
cout<<'?';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
cin>>val2;
int ans0=-1;
int ans1=-1;
if(val2<val1)
ans1=1;
else
ans0=1;
if(ans0==1)
{
    int l=1;
    int r=n;
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'1';
        for(int i=mid;i<n;i++)
        cout<<'0';
        fflush(stdout);
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans1=l;
}
else
{
    int l=1;
    int r=n;
    int mid;
    for(int i=0;i<n;i++)
    cout<<'1';
    cout<<endl;
    cin>>val1;
     while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'0';
        for(int i=mid;i<n;i++)
        cout<<'1';
        cout<<endl;
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans0=l;
}
cout<<'!'<<' '<<ans0<<' '<<ans1<<endl;
return ;
}
int main()
{
    ios_base::sync_with_stdio(false);
    Lets_be_precise;
    cin.tie(NULL);
    cout.tie(NULL);
    // #ifndef ONLINE_JUDGE
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    //#endif
    clock_t start, end;
    start = clock();
    int test=1;
    //cin>>test;
    for(int i=1;i<=test;i++)
    {
        solveforthiscase(i);
    }
     end = clock();
    long double time_taken = (long double)(end - start) /(long double)(CLOCKS_PER_SEC);
    cerr << "Time taken by program is : "<< (long double)time_taken*1000<< " milisec ";
}
inline ll max(ll a,ll b)
{return ((a>b)?a:b);}
inline ll min(ll a,ll b)
{return ((a>b)?b:a);}
inline ll gcd(ll a ,ll b)
{if(b==0) return a;a%=b;return gcd(b,a);}
inline void read(vector<ll> &v)
{for (int i = 0; i < v.size(); i++)cin>>v[i];}


 //Dragon_warrior7(IITK)
#pragma GCC optimize("O0")
#pragma GCC optimize ("Ofast")
#pragma GCC target ("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize ("-ffloat-store")
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define nl cout << '\n'
#define sor(x) sort(x.begin(), x.end())
#define rev(v) reverse(v.begin(), v.end())
#define lb(v, temp) lower_bound(v.begin(), v.end(), temp)
#define ub(v, temp) upper_bound(v.begin(), v.end(), temp)
#define fi first
#define se second
#define inf 1000000000000000000
#define pll pair<ll, ll>
#define vll vector<ll>
#define rub cerr << "\n------------------------------------\n"
#define deb(x) cerr<<#x<<' '<<'='<<' '<<x<<'\n'
#define Lets_be_precise cout<<fixed<<setprecision(10)
ll n,m,a,b,c,k,temp,x,y;
const int MAXN=100000+11;
inline void read(vector<ll> &v);
inline ll max(ll a,ll b);
inline ll min(ll a,ll b);
inline ll gcd(ll a ,ll b);
//#define cerr if(false)cerr
void solveforthiscase(const int & test)
{
cin>>n;
vector<char> v(n,'0');
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
v[0]='1';
int val1,val2;
cin>>val1;
cout<<'?';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
cin>>val2;
int ans0=-1;
int ans1=-1;
if(val2<val1)
ans1=1;
else
ans0=1;
if(ans0==1)
{
    int l=1;
    int r=n;
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'1';
        for(int i=mid;i<n;i++)
        cout<<'0';
        fflush(stdout);
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans1=l;
}
else
{
    int l=1;
    int r=n;
    int mid;
    for(int i=0;i<n;i++)
    cout<<'1';
    cout<<endl;
    cin>>val1;
     while(l<=r)
    {
        mid=(l+r)/2;
        for(int i=0;i<mid;i++)
        cout<<'0';
        for(int i=mid;i<n;i++)
        cout<<'1';
        cout<<endl;
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans0=l;
}
cout<<'!'<<' '<<ans0<<' '<<ans1<<endl;
return ;
}
int main()
{
    ios_base::sync_with_stdio(false);
    Lets_be_precise;
    cin.tie(NULL);
    cout.tie(NULL);
     #ifndef ONLINE_JUDGE
     freopen("input.txt", "r", stdin);
     freopen("output.txt", "w", stdout);
    #endif
    clock_t start, end;
    start = clock();
    int test=1;
    //cin>>test;
    for(int i=1;i<=test;i++)
    {
        solveforthiscase(i);
    }
     end = clock();
    long double time_taken = (long double)(end - start) /(long double)(CLOCKS_PER_SEC);
    cerr << "Time taken by program is : "<< (long double)time_taken*1000<< " milisec ";
}
inline ll max(ll a,ll b)
{return ((a>b)?a:b);}
inline ll min(ll a,ll b)
{return ((a>b)?b:a);}
inline ll gcd(ll a ,ll b)
{if(b==0) return a;a%=b;return gcd(b,a);}
inline void read(vector<ll> &v)
{for (int i = 0; i < v.size(); i++)cin>>v[i];}


 //Dragon_warrior7(IITK)
#pragma GCC optimize("O0")
#pragma GCC optimize ("Ofast")
#pragma GCC target ("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize ("-ffloat-store")
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define nl cout << '\n'
#define sor(x) sort(x.begin(), x.end())
#define rev(v) reverse(v.begin(), v.end())
#define lb(v, temp) lower_bound(v.begin(), v.end(), temp)
#define ub(v, temp) upper_bound(v.begin(), v.end(), temp)
#define fi first
#define se second
#define inf 1000000000000000000
#define pll pair<ll, ll>
#define vll vector<ll>
#define rub cerr << "\n------------------------------------\n"
#define deb(x) cerr<<#x<<' '<<'='<<' '<<x<<'\n'
#define Lets_be_precise cout<<fixed<<setprecision(10)
ll n,m,a,b,c,k,temp,x,y;
const int MAXN=100000+11;
inline void read(vector<ll> &v);
inline ll max(ll a,ll b);
inline ll min(ll a,ll b);
inline ll gcd(ll a ,ll b);
//#define cerr if(false)cerr
void solveforthiscase(const int & test)
{
cin>>n;
vector<char> v(n,'0');
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
v[0]='1';
int val1,val2;
cin>>val1;
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
cin>>val2;
int ans0=-1;
int ans1=-1;
if(val2<val1)
ans1=1;
else
ans0=1;
if(ans0==1)
{
    int l=1;
    int r=n;
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'1';
        for(int i=mid;i<n;i++)
        cout<<'0';
        cout<<endl;
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans1=l;
}
else
{
    int l=1;
    int r=n;
    int mid;
    cout<<'?'<<' ';
    for(int i=0;i<n;i++)
    cout<<'1';
    cout<<endl;
    cin>>val1;
     while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'0';
        for(int i=mid;i<n;i++)
        cout<<'1';
        cout<<endl;
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans0=l;
}
cout<<'!'<<' '<<ans0<<' '<<ans1<<endl;
return ;
}
int main()
{
    ios_base::sync_with_stdio(false);
    Lets_be_precise;
    cin.tie(NULL);
    cout.tie(NULL);
    // #ifndef ONLINE_JUDGE
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    //#endif
    clock_t start, end;
    start = clock();
    int test=1;
    //cin>>test;
    for(int i=1;i<=test;i++)
    {
        solveforthiscase(i);
    }
     end = clock();
    long double time_taken = (long double)(end - start) /(long double)(CLOCKS_PER_SEC);
    cerr << "Time taken by program is : "<< (long double)time_taken*1000<< " milisec ";
}
inline ll max(ll a,ll b)
{return ((a>b)?a:b);}
inline ll min(ll a,ll b)
{return ((a>b)?b:a);}
inline ll gcd(ll a ,ll b)
{if(b==0) return a;a%=b;return gcd(b,a);}
inline void read(vector<ll> &v)
{for (int i = 0; i < v.size(); i++)cin>>v[i];}


 //Dragon_warrior7(IITK)
#pragma GCC optimize("O0")
#pragma GCC optimize ("Ofast")
#pragma GCC target ("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize ("-ffloat-store")
#include "bits/stdc++.h"
using namespace std;
#define ll long long
#define pb push_back
#define nl cout << '\n'
#define sor(x) sort(x.begin(), x.end())
#define rev(v) reverse(v.begin(), v.end())
#define lb(v, temp) lower_bound(v.begin(), v.end(), temp)
#define ub(v, temp) upper_bound(v.begin(), v.end(), temp)
#define fi first
#define se second
#define inf 1000000000000000000
#define pll pair<ll, ll>
#define vll vector<ll>
#define rub cerr << "\n------------------------------------\n"
#define deb(x) cerr<<#x<<' '<<'='<<' '<<x<<'\n'
#define Lets_be_precise cout<<fixed<<setprecision(10)
ll n,m,a,b,c,k,temp,x,y;
const int MAXN=100000+11;
inline void read(vector<ll> &v);
inline ll max(ll a,ll b);
inline ll min(ll a,ll b);
inline ll gcd(ll a ,ll b);
//#define cerr if(false)cerr
void solveforthiscase(const int & test)
{
cin>>n;
vector<char> v(n,'0');
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
v[0]='1';
int val1,val2;
cin>>val1;
cout<<'?'<<' ';
for(int i=0;i<n;i++)
cout<<v[i];
cout<<endl;
cin>>val2;
int ans0=-1;
int ans1=-1;
if(val2<val1)
ans1=1;
else
ans0=1;
if(ans0==1)
{
    int l=1;
    int r=n;
    int mid;
    while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'1';
        for(int i=mid;i<n;i++)
        cout<<'0';
        fflush(stdout);
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans1=l;
}
else
{
    int l=1;
    int r=n;
    int mid;
    cout<<'?'<<' ';
    for(int i=0;i<n;i++)
    cout<<'1';
    cout<<endl;
    cin>>val1;
     while(l<=r)
    {
        mid=(l+r)/2;
        cout<<'?'<<' ';
        for(int i=0;i<mid;i++)
        cout<<'0';
        for(int i=mid;i<n;i++)
        cout<<'1';
        cout<<endl;
        int val;
        cin>>val;
        if(val<val1+mid)
        r=mid-1;
        else
        l=mid+1;
    }
    ans0=l;
}
cout<<'!'<<' '<<ans0<<' '<<ans1<<endl;
return ;
}
int main()
{
    ios_base::sync_with_stdio(false);
    Lets_be_precise;
    cin.tie(NULL);
    cout.tie(NULL);
    // #ifndef ONLINE_JUDGE
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    //#endif
    clock_t start, end;
    start = clock();
    int test=1;
    //cin>>test;
    for(int i=1;i<=test;i++)
    {
        solveforthiscase(i);
    }
     end = clock();
    long double time_taken = (long double)(end - start) /(long double)(CLOCKS_PER_SEC);
    cerr << "Time taken by program is : "<< (long double)time_taken*1000<< " milisec ";
}
inline ll max(ll a,ll b)
{return ((a>b)?a:b);}
inline ll min(ll a,ll b)
{return ((a>b)?b:a);}
inline ll gcd(ll a ,ll b)
{if(b==0) return a;a%=b;return gcd(b,a);}
inline void read(vector<ll> &v)
{for (int i = 0; i < v.size(); i++)cin>>v[i];}


// {{{ by unolight
#pragma region
#include <bits/stdc++.h>
#include <unistd.h>
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wunused-function"
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define RALL(x) rbegin(x),rend(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef int64_t LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

namespace { namespace unolight {
// Read Input
template<class T> void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
void _R( int64_t &x ) { scanf("%" PRId64,&x); }
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }
void R() {}
template<class T, class... U> void R( T& head, U&... tail ) { _R(head); R(tail...); }
// Write Output
template<class T> void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
void _W( const int64_t &x ) { printf("%" PRId64,x); }
void _W( const double &x ) { printf("%.16f\n",x); }
void _W( const char &x ) { putchar(x); }
void _W( const char *x ) { printf("%s",x); }
template<class T> void _W( const vector<T> &x ) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W( const T& head, const U&... tail ) { _W(head); putchar(sizeof...(tail)?' ':'\n'); W(tail...); }

#ifdef UNOLIGHT
#include "dump.hpp"
#else
#define dump(...)
#endif

template<class T> inline bool chmax( T &a, const T &b ) { return b>a ? a=b,true : false; }
template<class T> inline bool chmin( T &a, const T &b ) { return b<a ? a=b,true : false; }
template<class T> using MaxHeap = priority_queue<T>;
template<class T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
template<class T, class F=less<T>> void sort_uniq( vector<T> &v, F f=F() ) {
    sort(begin(v),end(v),f);
    v.resize(unique(begin(v),end(v))-begin(v));
}
#pragma endregion
// }}}

// 1. ask 00000,..
// 2. ask 10000,,.
// binary search ask 11111100...find the another bit
void main() {
    int n;
    R(n);
    VI a(n);
    auto Ask=[&]() {
        printf("? ");
        REP(i,n) printf("%d",a[i]);
        puts("");
        fflush(stdout);
        int x;
        R(x);
        return x;
    };
    int ans0=0, ans1=0;
    int base=Ask();
    a[0]=1;
    int d1=Ask();
    if ( d1<base ) ans1=1;
    else ans0=1;
    int l=1, r=n-1;
    while ( l<r ) {
        int m=(l+r)>>1;
        REP(i,n) a[i]=(i<m);
        int d2=Ask();
        bool ok=0;
        ok|=(ans0==1 && d2-d1<m-1); // find 1
        ok|=(ans1==1 && d1-d2<m-1); // find 0
        if ( ok ) r=m;
        else l=m+1;
    }
    if ( ans0 ) ans1=l+1;
    else ans0=l+1;
    printf("! %d %d\n", ans0, ans1);
    fflush(stdout);
}

 // {{{ main
}}
int main() { unolight::main(); return 0; }
// }}}


// {{{ by unolight
#pragma region
#include <bits/stdc++.h>
#include <unistd.h>
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wunused-function"
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define RALL(x) rbegin(x),rend(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef int64_t LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

namespace { namespace unolight {
// Read Input
template<class T> void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
void _R( int64_t &x ) { scanf("%" PRId64,&x); }
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }
void R() {}
template<class T, class... U> void R( T& head, U&... tail ) { _R(head); R(tail...); }
// Write Output
template<class T> void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
void _W( const int64_t &x ) { printf("%" PRId64,x); }
void _W( const double &x ) { printf("%.16f\n",x); }
void _W( const char &x ) { putchar(x); }
void _W( const char *x ) { printf("%s",x); }
template<class T> void _W( const vector<T> &x ) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W( const T& head, const U&... tail ) { _W(head); putchar(sizeof...(tail)?' ':'\n'); W(tail...); }

#ifdef UNOLIGHT
#include "dump.hpp"
#else
#define dump(...)
#endif

template<class T> inline bool chmax( T &a, const T &b ) { return b>a ? a=b,true : false; }
template<class T> inline bool chmin( T &a, const T &b ) { return b<a ? a=b,true : false; }
template<class T> using MaxHeap = priority_queue<T>;
template<class T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
template<class T, class F=less<T>> void sort_uniq( vector<T> &v, F f=F() ) {
    sort(begin(v),end(v),f);
    v.resize(unique(begin(v),end(v))-begin(v));
}
#pragma endregion
// }}}

// 1. ask 00000,..
// 2. ask 10000,,.
// binary search ask 11111100...find the another bit
void main() {
    int n;
    R(n);
    VI a(n);
    auto Ask=[&]() {
        printf("? ");
        REP(i,n) _W(a[i]);
        W("");
        fflush(stdout);
        int x;
        R(x);
        return x;
    };
    int ans0=0, ans1=0;
    int base=Ask();
    a[0]=1;
    int d1=Ask();
    if ( d1<base ) ans1=1;
    else ans0=1;
    int l=1, r=n-1;
    while ( l<r ) {
        int m=(l+r)>>1;
        REP(i,n) a[i]=(i<m);
        int d2=Ask();
        bool ok=0;
        ok|=(ans0==1 && d2-d1<m-1); // find 1
        ok|=(ans1==1 && d1-d2<m-1); // find 0
        if ( ok ) r=m;
        else l=m+1;
    }
    if ( ans0 ) ans1=l+1;
    else ans0=l+1;
    W('!',ans0,ans1);
    fflush(stdout);
}

 // {{{ main
}}
int main() { unolight::main(); return 0; }
// }}}


// {{{ by unolight
#pragma region
#include <bits/stdc++.h>
#include <unistd.h>
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wunused-function"
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define RALL(x) rbegin(x),rend(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef int64_t LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

namespace { namespace unolight {
// Read Input
template<class T> void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
void _R( int64_t &x ) { scanf("%" PRId64,&x); }
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }
void R() {}
template<class T, class... U> void R( T& head, U&... tail ) { _R(head); R(tail...); }
// Write Output
template<class T> void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
void _W( const int64_t &x ) { printf("%" PRId64,x); }
void _W( const double &x ) { printf("%.16f\n",x); }
void _W( const char &x ) { putchar(x); }
void _W( const char *x ) { printf("%s",x); }
template<class T> void _W( const vector<T> &x ) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W( const T& head, const U&... tail ) { _W(head); putchar(sizeof...(tail)?' ':'\n'); W(tail...); }

#ifdef UNOLIGHT
#include "dump.hpp"
#else
#define dump(...)
#endif

template<class T> inline bool chmax( T &a, const T &b ) { return b>a ? a=b,true : false; }
template<class T> inline bool chmin( T &a, const T &b ) { return b<a ? a=b,true : false; }
template<class T> using MaxHeap = priority_queue<T>;
template<class T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
template<class T, class F=less<T>> void sort_uniq( vector<T> &v, F f=F() ) {
    sort(begin(v),end(v),f);
    v.resize(unique(begin(v),end(v))-begin(v));
}
#pragma endregion
// }}}

// 1. ask 00000,..
// 2. ask 10000,,.
// binary search ask 11111100...find the another bit
void main() {
    int n;
    R(n);
    VI a(n);
    auto Ask=[&]() {
        printf("? ");
        REP(i,n) printf("%d",a[i]);
        puts("");
        fflush(stdout);
        int x;
        R(x);
        return x;
    };
    int ans0=0, ans1=0;
    int base=Ask();
    a[0]=1;
    int d1=Ask();
    if ( d1<base ) ans1=1;
    else ans0=1;
    int l=1, r=n-1;
    while ( l<r ) {
        int m=(l+r)>>1;
        REP(i,n) a[i]=(i<=m);
        int d2=Ask();
        bool ok=0;
        ok|=(ans0==1 && d2-d1<m); // find 1
        ok|=(ans1==1 && d1-d2<m); // find 0
        if ( ok ) r=m;
        else l=m+1;
    }
    if ( ans0 ) ans1=l+1;
    else ans0=l+1;
    printf("! %d %d\n", ans0, ans1);
    fflush(stdout);
}

 // {{{ main
}}
int main() { unolight::main(); return 0; }
// }}}


// {{{ by unolight
#pragma region
#include <bits/stdc++.h>
#include <unistd.h>
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wunused-function"
#define SZ(x) ((int)(x).size())
#define ALL(x) begin(x),end(x)
#define RALL(x) rbegin(x),rend(x)
#define REP(i,n) for ( int i=0; i<int(n); i++ )
#define REP1(i,a,b) for ( int i=(a); i<=int(b); i++ )
#define MP make_pair
#define PB push_back
using namespace std;
typedef int64_t LL;
typedef pair<int,int> PII;
typedef vector<int> VI;

namespace { namespace unolight {
// Read Input
template<class T> void _R( T &x ) { cin>>x; }
void _R( int &x ) { scanf("%d",&x); }
void _R( int64_t &x ) { scanf("%" PRId64,&x); }
void _R( double &x ) { scanf("%lf",&x); }
void _R( char &x ) { scanf(" %c",&x); }
void _R( char *x ) { scanf("%s",x); }
void R() {}
template<class T, class... U> void R( T& head, U&... tail ) { _R(head); R(tail...); }
// Write Output
template<class T> void _W( const T &x ) { cout<<x; }
void _W( const int &x ) { printf("%d",x); }
void _W( const int64_t &x ) { printf("%" PRId64,x); }
void _W( const double &x ) { printf("%.16f\n",x); }
void _W( const char &x ) { putchar(x); }
void _W( const char *x ) { printf("%s",x); }
template<class T> void _W( const vector<T> &x ) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W( const T& head, const U&... tail ) { _W(head); putchar(sizeof...(tail)?' ':'\n'); W(tail...); }

#ifdef UNOLIGHT
#include "dump.hpp"
#else
#define dump(...)
#endif

template<class T> inline bool chmax( T &a, const T &b ) { return b>a ? a=b,true : false; }
template<class T> inline bool chmin( T &a, const T &b ) { return b<a ? a=b,true : false; }
template<class T> using MaxHeap = priority_queue<T>;
template<class T> using MinHeap = priority_queue<T, vector<T>, greater<T>>;
template<class T, class F=less<T>> void sort_uniq( vector<T> &v, F f=F() ) {
    sort(begin(v),end(v),f);
    v.resize(unique(begin(v),end(v))-begin(v));
}
#pragma endregion
// }}}

// 1. ask 00000,..
// 2. ask 10000,,.
// binary search ask 11111100...find the another bit
void main() {
    int n;
    R(n);
    VI a(n);
    auto Ask=[&]() {
        _W("? ");
        REP(i,n) _W(a[i]);
        fflush(stdout);
        int x;
        R(x);
        return x;
    };
    int ans0=0, ans1=0;
    int base=Ask();
    a[0]=1;
    int d1=Ask();
    if ( d1<base ) ans1=1;
    else ans0=1;
    int l=1, r=n-1;
    while ( l<r ) {
        int m=(l+r)>>1;
        REP(i,n) a[i]=(i<m);
        int d2=Ask();
        bool ok=0;
        ok|=(ans0==1 && d2-d1<m-1); // find 1
        ok|=(ans1==1 && d1-d2<m-1); // find 0
        if ( ok ) r=m;
        else l=m+1;
    }
    if ( ans0 ) ans1=l+1;
    else ans0=l+1;
    W('!',' ',ans0,ans1);
}

 // {{{ main
}}
int main() { unolight::main(); return 0; }
// }}}