#include<bits/stdc++.h>
#define FOR(i, a, b) for (int i = (a), _b = (b); i <= _b; i++)
#define FORD(i, b, a) for (int i = (b), _a = (a); i >= _a; i--)
#define REP(i, n) for (int i = 0, _n = (n); i < _n; i++)
#define FORE(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); i++)
#define ALL(v) (v).begin(), (v).end()
#define fi first
#define se second
#define MASK(i) (1LL << (i))
#define BIT(x, i) (((x) >> (i)) & 1)
#define div _div
#define next _next
#define prev _prev
#define left _left
#define right _right
#define _builtinpopcount _builtinpopcountll
using namespace std; template < class X, class Y> bool minimize( X & x, const Y & y) { X eps = 1e-9 ; if ( x > y + eps) { x = y; return true ; } else return false ; } template < class X, class Y> bool maximize( X & x, const Y & y) { X eps = 1e-9 ; if ( x + eps < y) { x = y; return true ; } else return false ; } template < class T> T Abs( const T & x) { return ( x < 0 ? - x : x) ; }
/* Author: Van Hanh Pham */
/* END OF TEMPLATE - ACTUAL SOLUTION COMES HERE */
#define MAX 20002000
#define SQRT 4545
#define LENGTH 25
const int MOD = ( int ) 1e9 + 22071997 ;
int result[ MAX + 3 ] , pw[ SQRT + 3 ] [ LENGTH + 3 ] ; bool coprime[ SQRT + 3 ] [ SQRT + 3 ] ; int primeDiv[ MAX + 3 ] ; long long savedResult[ MAX + 3 ] ;
int getPw( int x, int k) { if ( k == 0 ) return 1 ; if ( k == 1 ) return x; return x > SQRT ? MAX + 1 : pw[ x] [ k] ; }
int getSum( int p, int q, int k) { long long res = 0 ; REP( i, k + 1 ) { res + = 1LL * getPw( p, i) * getPw( q, k - i) ; if ( res > MAX) return MAX; } return res; }
void prepare( void ) { REP( i, 2 ) primeDiv[ i] = - 1 ; for ( int i = 2 ; i * i <= MAX; i++ ) if ( primeDiv[ i] == 0 ) for ( int j = i * i; j <= MAX; j + = i) primeDiv[ j] = i; FOR( i, 2 , MAX) if ( primeDiv[ i] == 0 ) primeDiv[ i] = i;
FOR( i, 1 , SQRT) FOR( j, 1 , SQRT) coprime[ i] [ j] = true ;
FOR( i, 2 , SQRT) if ( primeDiv[ i] == i)
for ( int j = i; j <= SQRT; j + = i) for ( int k = i; k <= SQRT; k + = i) coprime[ j] [ k] = false ;
FOR( i, 1 , SQRT) {
pw[ i] [ 0 ] = 1 ;
FOR( j, 1 , LENGTH) pw[ i] [ j] = min( 1LL * MAX, 1LL * pw[ i] [ j - 1 ] * i) ;
}
FOR( k, 2 , LENGTH) FOR( q, 1 , SQRT) {
if ( pw[ q] [ k] >= MAX) break ;
FOR( p, q + 1 , SQRT) {
int sum = getSum( p, q, k) ;
if ( sum >= MAX) break ;
if ( ! coprime[ p] [ q] ) continue ;
result[ sum] ++ ;
}
}
}
vector< pair< int , int >> factors; void backtrack( int pos, int val, long long & sum) { if ( ( int ) pos >= factors.size ( ) ) { sum + = result[ val] ; return ; }
int tmp = val, pr = factors[ pos] .fi ;
FOR( i, 0 , factors[ pos] .se ) {
backtrack( pos + 1 , tmp, sum) ;
if ( i < factors[ pos] .se ) tmp * = pr;
}
}
int solve( int n) { if ( n < 3 ) return 0 ;
long long & res = savedResult[ n] ;
if ( res > 0 ) return res;
res = n % 2 == 0 ? n / 2 - 1 : n / 2 ;
factors.clear ( ) ;
while ( n > 1 ) {
int p = primeDiv[ n] ;
factors.push_back ( make_pair( p, 0 ) ) ;
while ( n % p == 0 ) {
factors.back ( ) .se ++ ;
n / = p;
}
}
backtrack( 0 , 1 , res) ;
return res % MOD;
}
int main( ) {
freopen ( "geometric.inp" , "r" , stdin ) ;
freopen ( "geometric.out" , "w" , stdout ) ;
prepare( ) ;
int input; scanf ( "%d" , & input) ;
while ( scanf ( "%d" , & input) == 1 ) printf ( "%d " , solve( input) ) ; printf ( "\n " ) ;
return 0 ;
}
I2luY2x1ZGU8Yml0cy9zdGRjKysuaD4KI2RlZmluZSBGT1IoaSwgYSwgYikgZm9yIChpbnQgaSA9IChhKSwgX2IgPSAoYik7IGkgPD0gX2I7IGkrKykKI2RlZmluZSBGT1JEKGksIGIsIGEpIGZvciAoaW50IGkgPSAoYiksIF9hID0gKGEpOyBpID49IF9hOyBpLS0pCiNkZWZpbmUgUkVQKGksIG4pIGZvciAoaW50IGkgPSAwLCBfbiA9IChuKTsgaSA8IF9uOyBpKyspCiNkZWZpbmUgRk9SRShpLCB2KSBmb3IgKF9fdHlwZW9mKCh2KS5iZWdpbigpKSBpID0gKHYpLmJlZ2luKCk7IGkgIT0gKHYpLmVuZCgpOyBpKyspCiNkZWZpbmUgQUxMKHYpICh2KS5iZWdpbigpLCAodikuZW5kKCkKI2RlZmluZSBmaSBmaXJzdAojZGVmaW5lIHNlIHNlY29uZAojZGVmaW5lIE1BU0soaSkgKDFMTCA8PCAoaSkpCiNkZWZpbmUgQklUKHgsIGkpICgoKHgpID4+IChpKSkgJiAxKQojZGVmaW5lIGRpdiBfZGl2CiNkZWZpbmUgbmV4dCBfbmV4dAojZGVmaW5lIHByZXYgX3ByZXYKI2RlZmluZSBsZWZ0IF9sZWZ0CiNkZWZpbmUgcmlnaHQgX3JpZ2h0CiNkZWZpbmUgX2J1aWx0aW5wb3Bjb3VudCBfYnVpbHRpbnBvcGNvdW50bGwKdXNpbmcgbmFtZXNwYWNlIHN0ZDsgdGVtcGxhdGU8Y2xhc3MgWCwgY2xhc3MgWT4gYm9vbCBtaW5pbWl6ZShYICZ4LCBjb25zdCBZICZ5KSB7IFggZXBzID0gMWUtOTsgaWYgKHggPiB5ICsgZXBzKSB7IHggPSB5OyByZXR1cm4gdHJ1ZTsgfSBlbHNlIHJldHVybiBmYWxzZTsgfSB0ZW1wbGF0ZTxjbGFzcyBYLCBjbGFzcyBZPiBib29sIG1heGltaXplKFggJngsIGNvbnN0IFkgJnkpIHsgWCBlcHMgPSAxZS05OyBpZiAoeCArIGVwcyA8IHkpIHsgeCA9IHk7IHJldHVybiB0cnVlOyB9IGVsc2UgcmV0dXJuIGZhbHNlOyB9IHRlbXBsYXRlPGNsYXNzIFQ+IFQgQWJzKGNvbnN0IFQgJngpIHsgcmV0dXJuICh4IDwgMCA/IC14IDogeCk7IH0KCi8qIEF1dGhvcjogVmFuIEhhbmggUGhhbSAqLwoKLyogRU5EIE9GIFRFTVBMQVRFIC0gQUNUVUFMIFNPTFVUSU9OIENPTUVTIEhFUkUgKi8KCiNkZWZpbmUgTUFYIDIwMDAyMDAwCiNkZWZpbmUgU1FSVCA0NTQ1CiNkZWZpbmUgTEVOR1RIIDI1CmNvbnN0IGludCBNT0QgPSAoaW50KTFlOSArIDIyMDcxOTk3OwoKaW50IHJlc3VsdFtNQVggKyAzXSwgcHdbU1FSVCArIDNdW0xFTkdUSCArIDNdOyBib29sIGNvcHJpbWVbU1FSVCArIDNdW1NRUlQgKyAzXTsgaW50IHByaW1lRGl2W01BWCArIDNdOyBsb25nIGxvbmcgc2F2ZWRSZXN1bHRbTUFYICsgM107CgppbnQgZ2V0UHcoaW50IHgsIGludCBrKSB7IGlmIChrID09IDApIHJldHVybiAxOyBpZiAoayA9PSAxKSByZXR1cm4geDsgcmV0dXJuIHggPiBTUVJUID8gTUFYICsgMSA6IHB3W3hdW2tdOyB9CgppbnQgZ2V0U3VtKGludCBwLCBpbnQgcSwgaW50IGspIHsgbG9uZyBsb25nIHJlcyA9IDA7IFJFUChpLCBrICsgMSkgeyByZXMgKz0gMUxMICogZ2V0UHcocCwgaSkgKiBnZXRQdyhxLCBrIC0gaSk7IGlmIChyZXMgPiBNQVgpIHJldHVybiBNQVg7IH0gcmV0dXJuIHJlczsgfQoKdm9pZCBwcmVwYXJlKHZvaWQpIHsgUkVQKGksIDIpIHByaW1lRGl2W2ldID0gLTE7IGZvciAoaW50IGkgPSAyOyBpICogaSA8PSBNQVg7IGkrKykgaWYgKHByaW1lRGl2W2ldID09IDApIGZvciAoaW50IGogPSBpICogaTsgaiA8PSBNQVg7IGogKz0gaSkgcHJpbWVEaXZbal0gPSBpOyBGT1IoaSwgMiwgTUFYKSBpZiAocHJpbWVEaXZbaV0gPT0gMCkgcHJpbWVEaXZbaV0gPSBpOwpGT1IoaSwgMSwgU1FSVCkgRk9SKGosIDEsIFNRUlQpIGNvcHJpbWVbaV1bal0gPSB0cnVlOwpGT1IoaSwgMiwgU1FSVCkgaWYgKHByaW1lRGl2W2ldID09IGkpCiAgICBmb3IgKGludCBqID0gaTsgaiA8PSBTUVJUOyBqICs9IGkpIGZvciAoaW50IGsgPSBpOyBrIDw9IFNRUlQ7IGsgKz0gaSkgY29wcmltZVtqXVtrXSA9IGZhbHNlOwoKRk9SKGksIDEsIFNRUlQpIHsKICAgIHB3W2ldWzBdID0gMTsKICAgIEZPUihqLCAxLCBMRU5HVEgpIHB3W2ldW2pdID0gbWluKDFMTCAqIE1BWCwgMUxMICogcHdbaV1baiAtIDFdICogaSk7Cn0KCkZPUihrLCAyLCBMRU5HVEgpIEZPUihxLCAxLCBTUVJUKSB7CiAgICBpZiAocHdbcV1ba10gPj0gTUFYKSBicmVhazsKICAgIEZPUihwLCBxICsgMSwgU1FSVCkgewogICAgICAgIGludCBzdW0gPSBnZXRTdW0ocCwgcSwgayk7CgogICAgICAgIGlmIChzdW0gPj0gTUFYKSBicmVhazsKICAgICAgICBpZiAoIWNvcHJpbWVbcF1bcV0pIGNvbnRpbnVlOwogICAgICAgIHJlc3VsdFtzdW1dKys7CiAgICB9Cn0KfQoKdmVjdG9yPHBhaXI8aW50LCBpbnQ+PiBmYWN0b3JzOyB2b2lkIGJhY2t0cmFjayhpbnQgcG9zLCBpbnQgdmFsLCBsb25nIGxvbmcgJnN1bSkgeyBpZiAoKGludClwb3MgPj0gZmFjdG9ycy5zaXplKCkpIHsgc3VtICs9IHJlc3VsdFt2YWxdOyByZXR1cm47IH0KaW50IHRtcCA9IHZhbCwgcHIgPSBmYWN0b3JzW3Bvc10uZmk7CkZPUihpLCAwLCBmYWN0b3JzW3Bvc10uc2UpIHsKICAgIGJhY2t0cmFjayhwb3MgKyAxLCB0bXAsIHN1bSk7CiAgICBpZiAoaSA8IGZhY3RvcnNbcG9zXS5zZSkgdG1wICo9IHByOwp9Cn0KCmludCBzb2x2ZShpbnQgbikgeyBpZiAobiA8IDMpIHJldHVybiAwOwpsb25nIGxvbmcgJnJlcyA9IHNhdmVkUmVzdWx0W25dOwppZiAocmVzID4gMCkgcmV0dXJuIHJlczsKCnJlcyA9IG4gJSAyID09IDAgPyBuIC8gMiAtIDEgOiBuIC8gMjsKCmZhY3RvcnMuY2xlYXIoKTsKd2hpbGUgKG4gPiAxKSB7CiAgICBpbnQgcCA9IHByaW1lRGl2W25dOwogICAgZmFjdG9ycy5wdXNoX2JhY2sobWFrZV9wYWlyKHAsIDApKTsKICAgIHdoaWxlIChuICUgcCA9PSAwKSB7CiAgICAgICAgZmFjdG9ycy5iYWNrKCkuc2UrKzsKICAgICAgICBuIC89IHA7CiAgICB9Cn0KCmJhY2t0cmFjaygwLCAxLCByZXMpOwoKcmV0dXJuIHJlcyAlIE1PRDsKCn0KCmludCBtYWluKCkgewpmcmVvcGVuKCJnZW9tZXRyaWMuaW5wIiwgInIiLCBzdGRpbik7CmZyZW9wZW4oImdlb21ldHJpYy5vdXQiLCAidyIsIHN0ZG91dCk7CnByZXBhcmUoKTsKaW50IGlucHV0OyBzY2FuZigiJWQiLCAmaW5wdXQpOwp3aGlsZSAoc2NhbmYoIiVkIiwgJmlucHV0KSA9PSAxKSBwcmludGYoIiVkICIsIHNvbHZlKGlucHV0KSk7IHByaW50ZigiXG4iKTsKcmV0dXJuIDA7Cn0=