結果
| 問題 |
No.950 行列累乗
|
| コンテスト | |
| ユーザー |
yosupot
|
| 提出日時 | 2019-12-13 00:30:40 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 6,100 bytes |
| コンパイル時間 | 1,622 ms |
| コンパイル使用メモリ | 106,896 KB |
| 最終ジャッジ日時 | 2025-01-08 10:59:02 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 TLE * 1 |
| other | AC * 17 TLE * 40 |
ソースコード
//#pragma GCC optimize("Ofast")
//#pragma GCC target("avx")
//#undef LOCAL
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;
template <class T, class U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
return os << "P(" << p.first << ", " << p.second << ")";
}
template <class T> ostream& operator<<(ostream& os, const V<T>& v) {
os << "[";
for (auto d : v) os << d << ", ";
return os << "]";
}
/*
int main() {
Scanner sc = Scanner(stdin);
Printer pr = Printer(stdout);
return 0;
}
*/
struct Scanner {
FILE* fp = nullptr;
char line[(1 << 15) + 1];
size_t st = 0, ed = 0;
void reread() {
memmove(line, line + st, ed - st);
ed -= st;
st = 0;
ed += fread(line + ed, 1, (1 << 15) - ed, fp);
line[ed] = '\0';
}
bool succ() {
while (true) {
if (st == ed) {
reread();
if (st == ed) return false;
}
while (st != ed && isspace(line[st])) st++;
if (st != ed) break;
}
if (ed - st <= 50) reread();
return true;
}
template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
bool read_single(T& ref) {
if (!succ()) return false;
while (true) {
succ();
size_t sz = 1;
while (st + sz < ed && !isspace(line[st + sz])) sz++;
ref.append(line + st, sz);
st += sz;
if (st != ed) break;
}
return true;
}
template <class T, enable_if_t<is_integral<T>::value, int> = 0>
bool read_single(T& ref) {
if (!succ()) return false;
bool neg = false;
if (line[st] == '-') {
neg = true;
st++;
}
ref = T(0);
while (isdigit(line[st])) {
ref = 10 * ref + (line[st++] - '0');
}
if (neg) ref = -ref;
return true;
}
template <class T> bool read_single(V<T>& ref) {
for (auto& d : ref) {
if (!read_single(d)) return false;
}
return true;
}
void read() {}
template <class H, class... T> void read(H& h, T&... t) {
bool f = read_single(h);
assert(f);
read(t...);
}
Scanner(FILE* _fp) : fp(_fp) {}
};
struct Printer {
public:
template <bool F = false> void write() {}
template <bool F = false, class H, class... T>
void write(const H& h, const T&... t) {
if (F) write_single(' ');
write_single(h);
write<true>(t...);
}
template <class... T> void writeln(const T&... t) {
write(t...);
write_single('\n');
}
Printer(FILE* _fp) : fp(_fp) {}
~Printer() { flush(); }
private:
static constexpr size_t SIZE = 1 << 15;
FILE* fp;
char line[SIZE], small[50];
size_t pos = 0;
void flush() {
fwrite(line, 1, pos, fp);
pos = 0;
}
void write_single(const char& val) {
if (pos == SIZE) flush();
line[pos++] = val;
}
template <class T, enable_if_t<is_same<T, string>::value, int> = 0>
void write_single(const T& val) {
for (char c : val) write_single(c);
}
template <class T, enable_if_t<is_integral<T>::value, int> = 0>
void write_single(T val) {
if (pos > (1 << 15) - 50) flush();
if (val == 0) {
write_single('0');
return;
}
if (val < 0) {
write_single('-');
val = -val; // todo min
}
size_t len = 0;
while (val) {
small[len++] = char('0' + (val % 10));
val /= 10;
}
reverse(small, small + len);
memcpy(line + pos, small, len);
pos += len;
}
template <class T> void write_single(const V<T>& val) {
auto n = val.size();
for (size_t i = 0; i < n; i++) {
if (i) write_single(' ');
write_single(val[i]);
}
}
};
#include <array>
Scanner sc = Scanner(stdin);
Printer pr = Printer(stdout);
using M = array<array<ll, 2>, 2>;
ll md;
M e() {
M m = M{};
m[0][0] = m[1][1] = 1;
return m;
}
M mul(M a, M b) {
M c = M();
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
c[i][j] += (a[i][k] * b[k][j]) % md;
}
c[i][j] %= md;
}
}
return c;
}
M pow_mod(M x, ll n) {
M r = e();
while (n) {
if (n & 1) r = mul(r, x);
x = mul(x, x);
n >>= 1;
}
return r;
}
const ll STEP = TEN(6);
ll discrete_logarithm_inside(M start, M x, M y) {
map<M, ll> mp;
M big = e(); // x^m
for (ll i = 0; i < STEP; i++) {
mp[y] = i;
y = mul(y, x);
big = mul(big, x);
}
for (ll step = 0; step < TEN(12); step += STEP) {
start = mul(start, big);
// check [step + 1, step + STEP]
if (mp.count(start)) {
return (step + STEP) - mp[start];
}
}
return -1;
}
ll discrete_logarithm(M x, M y) {
M start = e();
for (int i = 0; i < 100; i++) {
if (i && start == y) return i;
start = mul(start, x);
}
ll pred = 100 + discrete_logarithm_inside(start, x, y);
if (pow_mod(x, pred) != y) return -1;
return pred;
}
int main() {
M a, b;
sc.read(md);
sc.read(a[0][0], a[0][1], a[1][0], a[1][1]);
sc.read(b[0][0], b[0][1], b[1][0], b[1][1]);
ll u = discrete_logarithm(a, b);
pr.writeln(u);
return 0;
}
yosupot