#include<bits/stdc++.h> #include<atcoder/all> #define rep(i,n) for(int i=0;i<n;i++) using namespace std; using namespace atcoder; typedef long long ll; typedef vector<int> vi; typedef vector<long long> vl; typedef vector<vector<int>> vvi; typedef vector<vector<long long>> vvl; typedef long double ld; typedef pair<int, int> P; template <int m> ostream& operator<<(ostream& os, const static_modint<m>& a) {os << a.val(); return os;} template <int m> ostream& operator<<(ostream& os, const dynamic_modint<m>& a) {os << a.val(); return os;} template <int m> istream& operator>>(istream& is, static_modint<m>& a) {long long x; is >> x; a = x; return is;} template <int m> istream& operator>>(istream& is, dynamic_modint<m>& a) {long long x; is >> x; a = x; return is;} template<typename T> istream& operator>>(istream& is, vector<T>& v){int n = v.size(); assert(n > 0); rep(i, n) is >> v[i]; return is;} template<typename U, typename T> ostream& operator<<(ostream& os, const pair<U, T>& p){os << p.first << ' ' << p.second; return os;} template<typename T> ostream& operator<<(ostream& os, const vector<T>& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : " "); return os;} template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : ""); return os;} template<typename T> ostream& operator<<(ostream& os, const set<T>& se){for(T x : se) os << x << " "; os << "\n"; return os;} template<typename T> ostream& operator<<(ostream& os, const unordered_set<T>& se){for(T x : se) os << x << " "; os << "\n"; return os;} template<typename S, auto op, auto e> ostream& operator<<(ostream& os, const atcoder::segtree<S, op, e>& seg){int n = seg.max_right(0, [](S){return true;}); rep(i, n) os << seg.get(i) << (i == n - 1 ? "\n" : " "); return os;} template<typename S, auto op, auto e, typename F, auto mapping, auto composition, auto id> ostream& operator<<(ostream& os, const atcoder::lazy_segtree<S, op, e, F, mapping, composition, id>& seg){int n = seg.max_right(0, [](S){return true;}); rep(i, n) os << seg.get(i) << (i == n - 1 ? "\n" : " "); return os;} template<typename T> void chmin(T& a, T b){a = min(a, b);} template<typename T> void chmax(T& a, T b){a = max(a, b);} // Sieve of Eratosthenes // https://youtu.be/UTVg7wzMWQc?t=2774 struct Sieve { int n; vector<int> f, primes; Sieve(int n=1):n(n), f(n+1) { f[0] = f[1] = -1; for (long long i = 2; i <= n; ++i) { if (f[i]) continue; primes.push_back(i); f[i] = i; for (long long j = i*i; j <= n; j += i) { if (!f[j]) f[j] = i; } } } bool isPrime(int x) { return f[x] == x;} vector<int> factorList(int x) { vector<int> res; while (x != 1) { res.push_back(f[x]); x /= f[x]; } return res; } vector<pair<ll,int>> factor(ll x) { vector<pair<ll,int>> res; for (int p : primes) { int y = 0; while (x%p == 0) x /= p, ++y; if (y != 0) res.emplace_back(p,y); } if (x != 1) res.emplace_back(x,1); return res; } }; template<typename T> T pow_mod(T A, T N, T MOD){ T res = 1 % MOD; A %= MOD; while(N){ if(N & 1) res = (res * A) % MOD; A = (A * A) % MOD; N >>= 1; } return res; } int main(){ long long n; cin >> n; Sieve sieve(1000005); auto factor = sieve.factor(n); int two = 0; int five = 0; for(auto [key, val] : factor){ if(key == 2) two = val; if(key == 5) five = val; } assert(two == 0 or five == 0); if(two <= 3 and five <= 1){ int c = 1; long long phi = n; rep(_, two) c *= 2, phi /= 2; rep(_, five) c *= 5, phi /= 5; for(auto [p, e] : factor){ if(p == 2) continue; if(p == 5) continue; phi /= p; phi *= p - 1; } cout << "1\n"; cout << c << ' ' << 9 * phi << "\n"; return 0; } const int K = 12; const int L = 40; // n = 2^e2 * 5^e5 * m long long m = n; string s; if(two > 0){ long long x = 1; rep(i, two) x *= 2; m /= x; s = to_string(x); }else if(five > 0){ long long x = 1; rep(i, five) x *= 5; m /= x; s = to_string(x); }else{ assert(false); } while(s.size() < L){ s.insert(0, "0"); } string s_rev = s; reverse(s_rev.begin(), s_rev.end()); long long reminder = 0; rep(i, L) reminder += (s[i] - '0') * pow_mod<__uint128_t>(10, (L - 1) - i, m); rep(i, L) reminder += (s_rev[i] - '0') * pow_mod<__uint128_t>(10, (2 * L + 2 * K - 1) - i, m); reminder %= m; vector<long long> f(K); rep(i, K) f[i] += pow_mod<__uint128_t>(10, L + i, m); rep(i, K) f[(K - 1) - i] += pow_mod<__uint128_t>(10, L + i + K, m); vector<vector<long long>> g(K, vector<long long>(10)); rep(i, K) rep(num, 10) g[i][num] = (f[i] * num) % m; int K1 = (K + 1)/ 2; int K2 = K - K1; vector<vector<long long>> vec1(K1 + 1); vec1[0] = {0LL}; rep(i, K1){ for(auto val : vec1[i]){ if(i > 0){ vec1[i + 1].push_back(val); } for(int num = 1; num <= 9; num++){ long long val_next = val + g[i][num]; if(val_next >= m) val_next -= m; vec1[i + 1].push_back(val_next); } } } vector<vector<long long>> vec2(K2 + 1); vec2[0] = {reminder % m}; rep(i, K2){ for(auto val : vec2[i]){ for(int num = 0; num <= 9; num++){ long long val_next = val + g[K1 + i][num]; if(val_next >= m) val_next -= m; vec2[i + 1].push_back(val_next); } } } auto out = [&](long long val){ string u1, d1; string u2, d2; long long val1 = val; long long val2 = (2 * n - val) % m; for(int i = K1; i > 0; i--){ int num; for(num = 0; num <= 9; num++){ if(i == 1 and num == 0) continue; long long val = (val1 - g[i - 1][num] + m) % m; int idx = lower_bound(vec1[i - 1].begin(), vec1[i - 1].end(), val) - vec1[i - 1].begin(); if(idx < int(vec1[i - 1].size()) and vec1[i - 1][idx] == val) break; } { long long val = (val1 - g[i - 1][num] + m) % m; u1 += '0' + num; d1 += '0' + num; val1 = val; } } for(int i = K2; i > 0; i--){ int num; for(num = 0; num <= 9; num++){ long long val = (val2 - g[K1 + (i - 1)][num] + m) % m; int idx = lower_bound(vec2[i - 1].begin(), vec2[i - 1].end(), val) - vec2[i - 1].begin(); if(idx < int(vec2[i - 1].size()) and vec2[i - 1][idx] == val) break; } { long long val = (val2 - g[K1 + (i - 1)][num] + m) % m; u2 += '0' + num; d2 += '0' + num; val2 = val; } } reverse(u1.begin(), u1.end()); reverse(u2.begin(), u2.end()); cout << "3\n"; cout << s_rev << ' ' << "1\n"; cout << u1 << u2 << d2 << d1 << " 1\n"; cout << s << ' ' << "1\n"; return 0; }; rep(i, K1 + 1) sort(vec1[i].begin(), vec1[i].end()); rep(i, K2 + 1) sort(vec2[i].begin(), vec2[i].end()); { if(vec1[K1][0] == 0 and vec2[K2][0] == 0){ out(0LL); return 0; } } int idx = int(vec2[K2].size()) - 1; for(auto val1 : vec1[K1]){ if(val1 == 0) continue; long long val2 = (m - val1) % m; while(idx > 0){ if(vec2[K2][idx - 1] >= val2) idx--; else break; } if(vec2[K2][idx] == val2){ out(val1); return 0; } } assert(false); return 0; }