結果

問題 No.3170 [Cherry 7th Tune KY] Even if you could say "See you ..."
ユーザー ymm-knight
提出日時 2025-06-11 14:32:26
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
TLE  
実行時間 -
コード長 5,061 bytes
コンパイル時間 2,071 ms
コンパイル使用メモリ 210,940 KB
実行使用メモリ 48,676 KB
最終ジャッジ日時 2025-06-11 14:33:30
合計ジャッジ時間 50,822 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 37 TLE * 1 -- * 1
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
#define Loop(x,l,r) for (ll x = ll(l); x < ll(r); ++x)
#define LoopR(x,l,r) for (ll x = ll(r)-1; x >= ll(l); --x)
#define Looc(x,l,r) for (ll x = ll(l); x <= ll(r); ++x)
#define LoocR(x,l,r) for (ll x = ll(r); x >= ll(l); --x)
//#define int ll
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

#ifndef DB
#define DB 0
#define endl '\n'
#endif
#define debugl(l) if constexpr ((l) < DB)
#define debug debugl(0)

int mod;

ll pw(ll x, ll y) {
	ll a = 1;
	while (y) {
		if (y%2)
			a = a*x % mod;
		x = x*x % mod;
		y /= 2;
	}
	return a;
}
ll inv(ll x) { return pw(x, mod-2); }

struct Mat : array<ll, 4> {
	Mat operator*(const Mat &m) const {
		return {
			(at(0) * m[0] + at(1) * m[2]) % mod,
			(at(0) * m[1] + at(1) * m[3]) % mod,
			(at(2) * m[0] + at(3) * m[2]) % mod,
			(at(2) * m[1] + at(3) * m[3]) % mod,
		};
	}
	Mat &operator*=(const Mat &m) {
		return *this = *this * m;
	}
	ll det() const {
		return ((at(0) * at(3) - at(1) * at(2))%mod+mod)%mod;
	}
	Mat inv() const {
		return Mat{
			at(3),
			(mod - at(1)) % mod,
			(mod - at(2)) % mod,
			at(0),
		} * ::inv(det());
	}
	pll up  () const { return {at(0), at(1)}; }
	pll down() const { return {at(2), at(3)}; }
	
	Mat operator*(ll d) const {
		Mat ans = *this;
		for (auto &x : ans)
			x = x * d % mod;
		return ans;
	}
};

pll operator*(const pll &v, const Mat &m) {
	Mat vm = {
		v.first,
		v.second,
		0,
		0,
	};
	vm *= m;
	return {vm[0], vm[1]};
}

const Mat I = {1, 0, 0, 1};
Mat A, B, Ap;

map<ll, ll> up, down;

ll mypair(int x, int y) { return ((ll)x << 32) ^ y; }
ll mypair(pll p) { return mypair((int)p.first, (int)p.second); }

void solve_det0()
{
	int p = 0;
	Mat m = I;
	while (p < mod + 10 && m != B) {
		m *= A;
		p++;
	}
	cout << (m == B? p: -1) << '\n';
}

void make_updown()
{
	up.clear();
	down.clear();
	Mat m = I;
	Loop (i,0,mod) {
		m *= A;
		up  .insert({mypair(m.up  ()), i+1});
		down.insert({mypair(m.down()), i+1});
	}
	Ap = m;
}

ll find(const map<ll, ll> &small, pll target)
{
	ll p = 0;
	Mat mi = I;
	Mat Api = Ap.inv();
	Loop (_,0,mod) {
		// x * m = target
		// x = target * m.inv
		pll cand = target * mi;
		auto it = small.find(mypair(cand));
		if (it != small.end()) {
			debugl(1) {
				cerr << "find//////\n";
				cerr << cand.first << ' ' << cand.second << '\n';
				cerr << "*\n";
				auto m = mi.inv();
				cerr << m[0] << ' ' << m[1] << '\n';
				cerr << m[1] << ' ' << m[2] << '\n';
				cerr << "=\n";
				cerr << target.first << ' ' << target.second << '\n';
				cerr << "//////////\n";
			}
			return p + it->second;
		}
		mi *= Api;
		p += mod;
	}
	return -1;
}

vector<ll> coprimes(ll x)
{
	vector<ll> ans;
	for (ll y = 2; y*y <= x; y++) {
		if (x%y)
			continue;
		ll z = 1;
		while (x%y == 0) {
			z *= y;
			x /= y;
		}
		ans.push_back(z);
	}
	if (x)
		ans.push_back(x);
	return ans;
}

pll euc(ll x, ll y)
{
	ll a1 = 1, a2 = 0;
	ll b1 = 0, b2 = 1;
	while (y) {
		ll k = x/y;
		ll z = x - k*y;
		ll c1 = a1 - k*b1;
		ll c2 = a2 - k*b2;
		x = y; y = z;
		a1 = b1; b1 = c1;
		a2 = b2; b2 = c2;
	}
	return {a1, a2};
}

ll inv(ll n, ll m)
{
	auto [x, y] = euc(n, m);
	return (x%m+m)%m;
}

ll chinese_rem(ll m1, ll a1, ll m2, ll a2)
{
	ll g = gcd(m1, m2);
	if (a1 % g != a2 % g)
		return -1;
	ll a3 = a1 % g, m3 = g;
	m1 /= g; a1 %= m1;
	m2 /= g; a2 %= m2;

	vector<pll> vec;
	for (auto m : coprimes(m1))
		vec.push_back({m, a1%m});
	for (auto m : coprimes(m2))
		vec.push_back({m, a2%m});
	for (auto m : coprimes(m3))
		vec.push_back({m, a3%m});

	ll mf = m1*m2*m3;
	ll ans = 0;

	for (auto [m, a] : vec) {
		ll n = inv(mf/m, m);
		debug cerr << a << ' ' << n << ' ' << m << "!\n";
		ans = (ans + (__int128)a * (mf/m) % mf * n) % mf;
	}

	return ans;
}

Mat pw(Mat x, ll y) {
	Mat a = I;
	while (y) {
		if (y%2)
			a *= x;
		x *= x;
		y /= 2;
	}
	return a;
}

void solve()
{
	cin >> mod;
	Loop (i,0,4)
		cin >> A[i];
	Loop (i,0,4)
		cin >> B[i];

	if (A == B) {
		cout << "1\n";
		return;
	}
	if (B == I) {
		cout << "0\n";
		return;
	}
	if (A == Mat{}) {
		cout << "-1\n";
		return;
	}
	if (!A.det()) {
		return solve_det0();
	}

	make_updown();
	ll l1 = find(up  , {1, 0});
	ll l2 = find(down, {0, 1});
	ll p1 = find(up  , B.up  ());
	ll p2 = find(down, B.down());
	debug {
		cerr << "a % " << l1 << " = " << p1 << '\n';
		cerr << "a % " << l2 << " = " << p2 << '\n';
	}
	if (p1 == -1 || p2 == -1) {
		cout << "-1\n";
		return;
	}
	p1 %= l1;
	p2 %= l2;

	// n % l1 = p1
	// n % l2 = p2
	ll ans = chinese_rem(l1, p1, l2, p2);
	if (ans == -1) {
		cout << "-1\n";
		return;
	}

	debug {
		auto m = pw(A, ans);
		cerr << "debug///\n";
		cerr << m[0] << ' ' << m[1] << '\n';
		cerr << m[2] << ' ' << m[3] << '\n';
		if (m != B)
			cerr << "ERROR!!!!!!!!!!!!!!!!!!!\n";
		cerr << "////////\n";
	}
	debugl(1) {
		cerr << "l1///\n";
		auto m = pw(A, l1);
		cerr << m[0] << ' ' << m[1] << '\n';
		cerr << m[2] << ' ' << m[3] << '\n';
		cerr << "/////\n";
	}

	cout << ans << '\n';
}

signed main()
{
	cin.tie(0) -> sync_with_stdio(false);
	int t = 1;
	cin >> t;
	while (t--)
		solve();
}
0