import java.util.ArrayList;

public class Euler912 {

    static final long MOD = 1000000007L;

    static class Stats {
        long total = 0;
        long odd = 0;
        long oddMod = 0;
        long s1Mod = 0;
        long s2Mod = 0;
    }

    static long addMod(long a, long b) {
        long v = a + b;
        if (v >= MOD) {
            v -= MOD;
        }
        return v;
    }

    static long mulMod(long a, long b) {
        return (a * b) % MOD;
    }

    static class Solver {
        ArrayList<ArrayList<Stats>> memo = new ArrayList<>();
        ArrayList<ArrayList<Boolean>> seen = new ArrayList<>();

        Solver() {
            for (int c = 0; c < 3; ++c) {
                ArrayList<Stats> mList = new ArrayList<>();
                mList.add(new Stats());
                memo.add(mList);

                ArrayList<Boolean> sList = new ArrayList<>();
                sList.add(false);
                seen.add(sList);
            }
        }

        Stats empty() {
            return new Stats();
        }

        Stats merge(Stats left, Stats right) {
            if (left.total == 0)
                return right;
            if (right.total == 0)
                return left;

            Stats out = new Stats();
            out.total = left.total + right.total;
            out.odd = left.odd + right.odd;
            out.oddMod = addMod(left.oddMod, right.oddMod);

            long shift = left.total % MOD;
            long shift2 = mulMod(shift, shift);

            out.s1Mod = left.s1Mod;
            out.s1Mod = addMod(out.s1Mod, right.s1Mod);
            out.s1Mod = addMod(out.s1Mod, mulMod(shift, right.oddMod));

            out.s2Mod = left.s2Mod;
            out.s2Mod = addMod(out.s2Mod, right.s2Mod);
            out.s2Mod = addMod(out.s2Mod, mulMod((2 * shift) % MOD, right.s1Mod));
            out.s2Mod = addMod(out.s2Mod, mulMod(shift2, right.oddMod));

            return out;
        }

        Stats base(int c) {
            Stats s = new Stats();
            s.total = 1;
            s.odd = (c > 0) ? 1 : 0;
            s.oddMod = s.odd;
            s.s1Mod = s.odd;
            s.s2Mod = s.odd;
            return s;
        }

        Stats full(int c, int r) {
            if (r >= memo.get(c).size()) {
                while (memo.get(c).size() <= r) {
                    memo.get(c).add(new Stats());
                    seen.get(c).add(false);
                }
            }

            if (seen.get(c).get(r)) {
                return memo.get(c).get(r);
            }

            Stats out;
            if (r == 0) {
                out = base(c);
            } else {
                Stats left = full(0, r - 1);
                Stats right = (c < 2) ? full(c + 1, r - 1) : empty();
                out = merge(left, right);
            }

            seen.get(c).set(r, true);
            memo.get(c).set(r, out);
            return out;
        }

        Stats prefixStats(int c, int r, long k) {
            if (k == 0)
                return empty();

            Stats f = full(c, r);
            if (k >= f.total)
                return f;

            if (r == 0)
                return base(c);

            Stats left = full(0, r - 1);
            if (k <= left.total) {
                return prefixStats(0, r - 1, k);
            }

            Stats rightPart = prefixStats(c + 1, r - 1, k - left.total);
            return merge(left, rightPart);
        }

        long F(long n) {
            long remaining = n;
            long prefix = 0;
            long ans = 0;
            int length = 1;

            while (remaining > 0) {
                Stats block = full(1, length - 1);
                long take = (remaining < block.total) ? remaining : block.total;
                Stats chosen = (take == block.total) ? block : prefixStats(1, length - 1, take);

                long p = prefix % MOD;
                long p2 = mulMod(p, p);

                long contrib = 0;
                contrib = addMod(contrib, mulMod(chosen.oddMod, p2));
                contrib = addMod(contrib, mulMod((2 * p) % MOD, chosen.s1Mod));
                contrib = addMod(contrib, chosen.s2Mod);

                ans = addMod(ans, contrib);
                prefix += take;
                remaining -= take;
                ++length;
            }

            return ans;
        }
    }

    public static String solve() {
        Solver solver = new Solver();
        return Long.toString(solver.F(10000000000000000L));
    }

    public static void main(String[] args) {
        System.out.println(solve());
    }
}
