結果
問題 | No.526 フィボナッチ数列の第N項をMで割った余りを求める |
ユーザー |
![]() |
提出日時 | 2017-07-01 19:27:04 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 3 ms / 2,000 ms |
コード長 | 3,546 bytes |
コンパイル時間 | 968 ms |
コンパイル使用メモリ | 93,160 KB |
実行使用メモリ | 6,820 KB |
最終ジャッジ日時 | 2024-10-05 00:04:02 |
合計ジャッジ時間 | 1,745 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 12 |
ソースコード
#include <cstdio>#include <cassert>#include <cmath>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <map>#include <set>#include <functional>#include <stack>#include <queue>#include <tuple>#define getchar getchar_unlocked#define putchar putchar_unlocked#define _rep(_1, _2, _3, _4, name, ...) name#define rep2(i, n) rep3(i, 0, n)#define rep3(i, a, b) rep4(i, a, b, 1)#define rep4(i, a, b, c) for (int i = int(a); i < int(b); i += int(c))#define rep(...) _rep(__VA_ARGS__, rep4, rep3, rep2, _)(__VA_ARGS__)using namespace std;using i64 = long long;using u8 = unsigned char;using u32 = unsigned;using u64 = unsigned long long;using f80 = long double;int get_int() {int c, n;while ((c = getchar()) < '0');n = c - '0';while ((c = getchar()) >= '0') n = n * 10 + (c - '0');return n;}struct Mod64 {using u128 = __uint128_t;Mod64() : n_(0) {}Mod64(u64 n) : n_(init(n)) {}static void set_mod(u64 m) {shift = __builtin_ctzll(m);mask = (u64(1) << shift) - 1;mod = m >> shift; assert(mod & 1);inv = mod; rep(i, 5) inv *= 2 - inv * mod;assert(mod * inv == 1);r2 = -u128(mod) % mod;one = u64(1) << shift | 1;}static u64 modulus() { return mod << shift; }static u64 init(u64 x) {return reduce_odd(u128(x) * r2) << shift | (x & mask);}static u64 reduce_odd(u128 x) {u64 y = u64(x >> 64) - u64((u128(u64(x) * inv) * mod) >> 64);return i64(y) < 0 ? y + mod : y;}static u64 reduce(u64 x0, u64 x1) {u64 y = reduce_odd(u128(x0 >> shift) * (x1 >> shift));return y << shift | ((x0 * x1) & mask);}Mod64& operator += (Mod64 rhs) {u64 hi = (n_ >> shift) + (rhs.n_ >> shift) - mod;if (i64(hi) < 0) hi += mod;n_ = hi << shift | ((n_ + rhs.n_) & mask);return *this;}Mod64& operator -= (Mod64 rhs) {u64 hi = (n_ >> shift) - (rhs.n_ >> shift);if (i64(hi) < 0) hi += mod;n_ = hi << shift | ((n_ - rhs.n_) & mask);return *this;}Mod64& operator *= (Mod64 rhs) { n_ = reduce(n_, rhs.n_); return *this; }Mod64 operator + (Mod64 rhs) const { return Mod64(*this) += rhs; }Mod64 operator - (Mod64 rhs) const { return Mod64(*this) -= rhs; }Mod64 operator * (Mod64 rhs) const { return Mod64(*this) *= rhs; }u64 get() const {u64 ret = reduce(n_, one);u64 r1 = ret >> shift;return mod * (((ret - r1) * inv) & mask) + r1;}void set(u64 n) { n_ = n; }Mod64 pow(u64 exp) const {Mod64 ret = Mod64(1);for (Mod64 base = *this; exp; exp >>= 1, base *= base) if (exp & 1) ret *= base;return ret;}Mod64 inverse() const { return pow(mod - 2); }friend ostream& operator << (ostream& os, const Mod64& m) { return os << m.get(); }static u64 mod, inv, r2, mask, one;static int shift;u64 n_;};u64 Mod64::mod, Mod64::inv, Mod64::r2, Mod64::mask, Mod64::one;int Mod64::shift;template <typename Mod>Mod fib(u64 n) {if (n <= 2) return Mod((n + 1) >> 1);Mod a = Mod(1), b = a;for (u64 mask = u64(1) << __lg(n >> 1); mask; mask >>= 1) {Mod t = a * a + b * b;if (n & mask) {b *= (a + a + b), a = t;} else {a *= (b + b - a), b = t;}}return a;}void solve() {u64 N, M;while (~scanf("%llu %llu", &N, &M)) {Mod64::set_mod(M);printf("%llu\n", fib<Mod64>(N - 1).get());}}int main() {clock_t beg = clock();solve();clock_t end = clock();fprintf(stderr, "%.3f sec\n", double(end - beg) / CLOCKS_PER_SEC);return 0;}