Mà càng đọc càng thấy giống bài Fibonacci nhỉ. Cuối cùng cũng hiểu hết.ngồi xóa bớt mấy hàm ko cần thiết còn4450 dòng
đo đạc lại thấy nếu bỏoperator*=
khỏiSqrtSum
thì MSVC nó ko optimize được hay sao ấy mà chạy mất 0.6s thay vì 0.36s đành phải cho vào lại cộng thêm 6 dòng
C++:template <uint32_t Order> struct IntMod { uint32_t val = 0; explicit constexpr IntMod(uint64_t n) : val{static_cast<uint32_t>(n % Order)} {} constexpr IntMod operator-() const { return IntMod{Order - val}; } constexpr IntMod operator+(const IntMod& rhs) const { return IntMod{static_cast<uint64_t>(val) + rhs.val}; } constexpr IntMod operator*(const IntMod& rhs) const { return IntMod{static_cast<uint64_t>(val) * rhs.val}; } constexpr IntMod operator/(const IntMod& rhs) const { return *this * rhs.inv(); } constexpr IntMod inv() const { IntMod res{1}, a{*this}; for (uint32_t p = Order - 2; p; p >>= 1, a = a * a) if (p & 1) res = res * a; return res; } }; template <class T, size_t SqrtValue> struct SqrtSum { T rp{0}; // rational part T ip{0}; // irrational part constexpr SqrtSum(T rp, T ip = T{0}) : rp(rp), ip(ip) {} constexpr SqrtSum& operator*=(const SqrtSum& rhs) { // faster in MSVC const T temp = rp * rhs.rp + ip * rhs.ip * T{SqrtValue}; ip = rp * rhs.ip + ip * rhs.rp; rp = temp; return *this; } constexpr SqrtSum operator+(const SqrtSum& rhs) const { return SqrtSum{rp + rhs.rp, ip + rhs.ip}; } constexpr SqrtSum operator*(const SqrtSum& rhs) const { return SqrtSum{*this} *= rhs; } constexpr SqrtSum pow(uint32_t p) const { SqrtSum res = T{1}, a = *this; for (; p; p >>= 1, a *= a) if (p & 1) res *= a; return res; } }; struct Solution { using Mint = IntMod<1'000'000'007>; using Sqrt5Sum = SqrtSum<Mint, 5>; int knightDialer(int n) { if (n == 1) return 10; constexpr Sqrt5Sum e1{Mint{3}, Mint{1}}; constexpr Sqrt5Sum e3{Mint{3}, -Mint{1}}; constexpr Sqrt5Sum d1a{Mint{1}, Mint{2} / Mint{5}}; constexpr Sqrt5Sum d1b{Mint{1} / Mint{2}, Mint{3} / Mint{20}}; constexpr Sqrt5Sum d3a{Mint{1}, -(Mint{2} / Mint{5})}; constexpr Sqrt5Sum d3b{Mint{9} / Mint{8}, -(Mint{19} / Mint{40})}; constexpr Sqrt5Sum kTwo{Mint{2}}; return (kTwo * (n % 2 ? e1.pow(n/2) * d1b * e1 + e3.pow(n/2) * d3b * kTwo : e1.pow(n/2) * d1a + e3.pow(n/2) * d3a)).rp.val; } };
Đống template với Operator cho thành hàm bình thường ok mà, nhưng chắc chạy chậm hơn tí.