#include<bits/stdc++.h>
#define pb push_back
#define PI acos(-1)
#define mp make_pair
#define F first
#define sd(x) scanf("%d",&x)
#define sd2(x,y) scanf("%d%d",&x,&y)
#define sdl(x) scanf("%lld",&x)
#define sd2l(x,y) scanf("%lld%lld",&x,&y)
#define S second
#define ll long long int
#define inf 1000000014
#define infl (ll)(1e18+250)
#define sz(x) (int) x.size()
#define pi pair< int , int >
#define pil pair <pi, pi>
#define pii pair<int, pair>
#define nax 201010
#define pu push
#define trace1(x) cerr << #x << ": " << x << endl
#define trace2(x, y) cerr << #x << ": " << x << " | " << #y << ": " << y << endl
using namespace std;
#define ll long long int
#define MOD 100000007
#define MAX 5000550
int cnt[MAX];
pi v[MAX][13];
vector < pi > query;
vector < int > primes;
int occ[MAX];
int latest[MAX];
ll times[MAX];
int prime_mapping[MAX];
long long int fans[110];
ll cnt_primes[MAX];
int query_cnt;
void pre()
{
// prime factorization
int ctr,cpy;
for(int i = 2; i <= 5000100; i++)
{
if(cnt[i] == 0)
{
primes.push_back(i); // indexing the primes.
prime_mapping[i] = sz(primes) - 1; // prime to index mapping
for(int j = i ; j <= 5000100; j+=i)
{
cpy = j;
ctr = 0;
while(cpy % i == 0)
{
cpy /= i;
ctr++;
}
v[j][cnt[j]++] = make_pair(i,ctr); // stores the pair <prime_factor, its count> for element j
}
}
}
}
void solve()
{
// We try to answer all queries in one pass through all the elements , for this we order the queries in ascending order and answer
ll cur_ans;int siz, num, count;
int query_ptr = 0;
// trivial case n = 1; note after sorting the queries n = 1 will occur at the start so we first deal with them
while(query_ptr <= query_cnt && query[query_ptr].first == 1)
{
fans[query[query_ptr].second] = 1;
query_ptr++;
}
/*
We update two arrays on the fly , occ and cnt_primes
at any iteration i occ[x] (x = prime) holds the number of times x occurs in factorization of factorial (i)
Similarly for iteration i cnt_primes[x] holds the number of times x occurs in prime factorization of AF(i)
latest[x] (x = prime) holds the last value till which we have calculated the number of times x occurs in prime factorization of i
The trick is that although prime_factor x occurs in all factorials > x, we update the occ , latest and cnt_primes arrays only
when i % x == 0. We can do so because between any two successive multiples of x say A and B all numbers in [A, B) will have same number of
x in prime factorization of their factorial. This is clear because no multiple of x occurs in (A,B) so once you calculate the requiste values for
A for all factorials A+1, A+2, A+x-1 the number of x's remain constant (occ[x]). Notice this in line 90.
*/
for(int i = 2; i <= 5000000; i++)
{
siz = cnt[i];
for(int j = 0; j < siz ; j++)
{
num = v[i][j].first;
count = v[i][j].second;
if(latest[num] != 0)
cnt_primes[prime_mapping[num]] = (cnt_primes[prime_mapping[num]] + occ[num]*1ll*(i - latest[num] - 1) ) % MOD;
occ[num] += count;
cnt_primes[prime_mapping[num]] += occ[num];
latest[num] = i;
}
/* Explanation of answering query.
Suppose we want to find the answer for element i. Notice that for any prime number(x) < i we would have the correct answer till just smaller
multiple of x i.e till [i / x](integer division) * i (denoted by Y)using the above methodology. Now we would have to add the number of times x occurs in the range
[Y + 1 , i]. We again use the same argument we used to justify first loop, which is that the number of times x occurs in factorials in range (Y+1, I] would be constant
Hence the similar term in line 109. Accordingly we also modify lates[x] denoting that we have the number of times prime factor x occurs in AF[i] , till
number i
*/
if(query_ptr <= query_cnt && query[query_ptr].first == i)
{
int psiz = sz(primes);
int prime_ptr = 0;
ll cans = 1;
while(primes[prime_ptr] <= i)
{
cnt_primes[prime_ptr] = (cnt_primes[prime_ptr] + occ[primes[prime_ptr]]*1ll*(i - latest[primes[prime_ptr]]) ) % MOD;
cans = cans * (cnt_primes[prime_ptr] + 1) % MOD;
latest[primes[prime_ptr]] = i;
prime_ptr++;
}
while(query_ptr <= query_cnt && query[query_ptr].first == i)
{
fans[query[query_ptr].second] = cans;
query_ptr++;
}
}
if(query_ptr > query_cnt)
break;
}
for(int i = 0; i < query_cnt; i++)
printf("%lld\n", fans[i]);
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int n;
pre();
while(cin >> n)
{
if(n == 0)
break;
query.push_back(make_pair(n , query_cnt));
query_cnt++;
}
sort(query.begin(), query.end()); // ordering the queries in ascending order
solve();
return 0;
}