#ifndef __INTMOD_H__0001__ #define __INTMOD_H__0001__ #include #include #include #include /* Modulus must be less than 0x80000000, and not be 0. */ template class IntMod { typedef int32_t Int; typedef uint32_t UInt; typedef long long Long; typedef uint64_t ULong; public: template friend bool operator==(const IntMod& left, const IntMod& right); template friend bool operator!=(const IntMod& left, const IntMod& right); template friend bool operator<(const IntMod& left, const IntMod& right); template friend bool operator<=(const IntMod& left, const IntMod& right); template friend bool operator>(const IntMod& left, const IntMod& right); template friend bool operator>=(const IntMod& left, const IntMod& right); private: UInt value_m; public: IntMod() { value_m = 0; } IntMod(UInt value) { value_m = value % Modulus; } IntMod(ULong value) { value_m = value % Modulus; } IntMod(Int value) { Int tmp = value % (Int)Modulus; value_m = tmp >= 0 ? tmp : Modulus - (unsigned int)(-tmp); } IntMod(Long value) { Int tmp = value % (Long)Modulus; value_m = tmp >= 0 ? tmp : Modulus - (unsigned int)(-tmp); } IntMod(const IntMod& other) : value_m(other.value_m) {} IntMod& operator=(const IntMod& other) { value_m = other.value_m; return *this; } const IntMod& operator+() const { return *this; } IntMod operator-() const { return IntMod(Modulus - value_m); } IntMod& operator++() { ++value_m; if (value_m == Modulus) value_m = 0; return *this; } IntMod& operator--() { if (value_m == 0) value_m = Modulus; --value_m; return *this; } IntMod operator++(int dummy) { IntMod tmp(*this); ++(*this); return tmp; } IntMod operator--(int dummy) { IntMod tmp(*this); --(*this); return tmp; } IntMod& operator+=(const IntMod& right) { value_m += right.value_m; // value_m < 0x80000000 if (value_m >= Modulus) value_m -= Modulus; return *this; } IntMod& operator-=(const IntMod& right) { if (value_m < right.value_m) value_m += Modulus; value_m -= right.value_m; return *this; } IntMod& operator*=(const IntMod& right) { value_m = ((ULong)value_m * right.value_m) % Modulus; return *this; } IntMod& operator/=(const IntMod& right) { (*this) *= (right.Inverse()); return *this; } // for power IntMod operator[](ULong exp) const { return Pow(exp); } /* Modulus must be a prime. */ IntMod Inverse() const { return (*this).Pow(Modulus - 2); } IntMod Pow(ULong exp) const { IntMod product = 1; IntMod factor(*this); while (exp > 0) { if (exp & 1) product *= factor; factor *= factor; exp >>= 1; } return product; } UInt Get_value() const { return value_m; } static IntMod Fact(UInt num) { static std::vector table(1, 1); if (table.size() > num) return table[num]; int old_size = table.size(); table.resize(num + 1); for (int i = old_size; i <= num; i++) { table[i] = table[i - 1] * i; } return table[num]; } static IntMod Combi(UInt n, UInt r) { if (n < r) throw "okashii"; return IntMod::Fact(n) / (IntMod::Fact(n - r) * IntMod::Fact(r)); } static std::vector Inverse_list(int size) { assert(size < Modulus); std::vector ret_arr(size + 1); ret_arr[1] = 1; for (int i = 2; i <= size; ++i) { ret_arr[i] = ((ULong)(Modulus - Modulus / i) * ret_arr[Modulus % i].Get_value()) % Modulus; } return ret_arr; } }; template IntMod operator+(const IntMod& left, const IntMod& right) { IntMod ret(left); ret += right; return ret; } template IntMod operator-(const IntMod& left, const IntMod& right) { IntMod ret(left); ret -= right; return ret; } template IntMod operator*(const IntMod& left, const IntMod& right) { IntMod ret(left); ret *= right; return ret; } template IntMod operator/(const IntMod& left, const IntMod& right) { IntMod ret(left); ret /= right; return ret; } template bool operator==(const IntMod& left, const IntMod& right) { return left.value_m == right.value_m; } template bool operator!=(const IntMod& left, const IntMod& right) { return left.value_m != right.value_m; } /* for set/map */ template bool operator<(const IntMod& left, const IntMod& right) { return left.value_m < right.value_m; } template bool operator<=(const IntMod& left, const IntMod& right) { return left.value_m <= right.value_m; } template bool operator>(const IntMod& left, const IntMod& right) { return left.value_m > right.value_m; } template bool operator>=(const IntMod& left, const IntMod& right) { return left.value_m >= right.value_m; } template IntMod operator+(const IntMod& left, Integer right) { return left + IntMod(right); } template IntMod operator+(Integer left, const IntMod& right) { return IntMod(left) + right; } template IntMod operator-(const IntMod& left, Integer right) { return left - IntMod(right); } template IntMod operator-(Integer left, const IntMod& right) { return IntMod(left) - right; } template IntMod operator*(const IntMod& left, Integer right) { return left * IntMod(right); } template IntMod operator*(Integer left, const IntMod& right) { return IntMod(left) * right; } template IntMod operator/(const IntMod& left, Integer right) { return left / IntMod(right); } template IntMod operator/(Integer left, const IntMod& right) { return IntMod(left) / right; } template std::istream& operator<<(std::istream& ist, const IntMod& val) { uint64_t tmp; ist >> tmp; val = tmp; return ist; } template std::ostream& operator<<(std::ostream& ost, const IntMod& val) { ost << val.Get_value(); return ost; } typedef IntMod<1000000007> MInt; #if 1 MInt operator"" _m(unsigned long long num) { return MInt((uint64_t)num); } #endif #endif #define _CRT_SECURE_NO_WARNINGS #define _SCL_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef unsigned int uint; typedef long long LL; typedef unsigned long long ULL; typedef pair PP; #define REP(i, a, n) for(LL i = (a), i##_max = (n); i < i##_max; ++i) #define REM(i, a, n) for(LL i = (LL)(n) - 1, i##min = (a); i >= i##min; --i) #define ALL(arr) (arr).begin(), (arr).end() #define FLOAT fixed << setprecision(16) #define SPEEDUP {cin.tie(NULL); ios::sync_with_stdio(false);} const int INF = 0x3FFFFFFF; const LL INFLL = 0x3FFFFFFF3FFFFFFF; const double INFD = 1.0e+308; const string INFSTR = "\x7f"; const double EPS = 1.0e-9; void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; } void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; } template istream& operator>>(istream& ist, pair& right) { return ist >> right.first >> right.second; } template ostream& operator<<(ostream& ost, const pair& right) { return ost << right.first << ' ' << right.second; } template void Fill(T(&dest)[N], const TCompatible& val) { fill(dest, dest + N, val); } template void Fill(T(&dest)[M][N], const TCompatible& val) { for (int i = 0; i < M; ++i) Fill(dest[i], val); } template T Compare(T left, T right) { return left > right ? 1 : (left < right ? -1 : 0); } istream& Ignore(istream& ist) { string s; ist >> s; return ist; } bool Inside(int i, int j, int h, int w) { return i >= 0 && i < h && j >= 0 && j < w; } template T Next() { T buf; cin >> buf; return buf; } #ifdef ONLY_MY_ENVIR #include "IntMod.h" #include "Union_Find.h" #include "Graph.h" #include "Range.h" #include "Global.h" #include "Flow_Solver.h" #include "Tree.h" #include "Suffix_Array.h" #include "Geometry.h" #include "Matrix.h" #include "Segment_Tree.h" #include "Rational.h" #include "Position.h" #endif #ifdef __GNUC__ typedef __int128 LLL; istream& operator>> (istream& ist, __int128& val) { LL tmp; ist >> tmp; val = tmp; return ist; } ostream& operator<< (ostream& ost, __int128 val) { LL tmp = val; ost << tmp; return ost; } #endif #if 1234567891 #include #include #include #include template using PriorityQ = priority_queue, greater >; // コスト小を優先 template auto Is(const T& value) { return [value](const auto& comparand) -> bool { return comparand == value; }; } #endif struct Mat { ULL a, b, c, d; }; Mat operator*(const Mat& p, const Mat& q) { return { p.a * q.a + p.b * q.c, p.a * q.b + p.b * q.d, p.c * q.a + p.d * q.c, p.c * q.b + p.d * q.d }; } Mat operator%(const Mat& p, uint mod) { return { p.a % mod, p.b % mod, p.c % mod, p.d % mod }; } Mat Pow(const Mat& p, uint exp, uint mod) { if (exp == 0) return Mat{ 1, 0, 0, 1 }; if (exp % 2 == 1) return p * Pow(p, exp - 1, mod) % mod; Mat tmp = Pow(p, exp / 2, mod); return tmp * tmp % mod; } bool Is_unit(const Mat& p) { return p.a == 1 && p.b == 0 && p.c == 0 && p.d == 1; } map Factor(uint n) { map ret; for (int i = 2; i * i <= n; ++i) { while (n % i == 0) { n /= i; ++ret[i]; } } if (n != 1) ++ret[n]; return ret; } uint Pow(uint base, uint exp) { if (exp == 0) return 1; if (exp % 2 == 1) return base * Pow(base, exp - 1); uint tmp = Pow(base, exp / 2); return tmp * tmp; } uint Period(uint mod, uint expected_period) { const auto& factors = Factor(expected_period); const int N = factors.size(); const Mat fib_gene = Mat{ 1, 1, 1, 0 }; vector mats; for (auto factor : factors) { mats.push_back(Pow(fib_gene, factor.first, mod)); } uint mn = 0xffffffff; vector curr(N, 0); //curr.back() = 1; while (curr[0] <= factors.begin()->second) { Mat product = fib_gene; auto fit = factors.cbegin(); for (int i = 0; i < N; ++i, ++fit) { for (int j = 0; j < curr[i]; ++j) { product = Pow(product, fit->first, mod); } } if (Is_unit(product)) { uint ans = 1; auto it = factors.cbegin(); for (int i = 0; i < N; ++i, ++it) { ans *= Pow(it->first, curr[i]); } mn = min(mn, ans); } ++curr.back(); auto it = prev(factors.cend()); for (int i = N - 1; i > 0 && curr[i] > it->second; --i, --it) { curr[i] = 0; ++curr[i - 1]; } } return mn; } int main() { int N; cin >> N; MInt ans = 1; for (int i = 0; i < N; ++i) { uint p, k; cin >> p >> k; uint period; if (p == 2) { period = 3; } else if (p == 5) { period = 20; } else { uint r = p * p % 5; uint expected_period = (r == 1 ? p - 1 : 2 * p + 2); period = Period(p, expected_period); } ans *= period * MInt(p)[k - 1]; } cout << ans << endl; return 0; }