結果

問題 No.186 中華風 (Easy)
ユーザー morimariomorimario
提出日時 2021-05-06 20:30:27
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 5,010 bytes
コンパイル時間 2,317 ms
コンパイル使用メモリ 208,256 KB
実行使用メモリ 4,476 KB
最終ジャッジ日時 2023-10-12 12:57:09
合計ジャッジ時間 3,545 ms
ジャッジサーバーID
(参考情報)
judge15 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,352 KB
testcase_01 WA -
testcase_02 WA -
testcase_03 AC 1 ms
4,348 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 WA -
testcase_10 AC 1 ms
4,348 KB
testcase_11 WA -
testcase_12 WA -
testcase_13 WA -
testcase_14 WA -
testcase_15 AC 1 ms
4,352 KB
testcase_16 WA -
testcase_17 WA -
testcase_18 WA -
testcase_19 AC 1 ms
4,348 KB
testcase_20 AC 1 ms
4,352 KB
testcase_21 AC 2 ms
4,352 KB
testcase_22 AC 2 ms
4,348 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
main.cpp: 関数 ‘pll my_crt(vl, vl)’ 内:
main.cpp:150:32: 警告: ‘z’ may be used uninitialized [-Wmaybe-uninitialized]
  150 |                 return pll(0, 1);
      |                                ^
main.cpp:148:15: 備考: ‘z’ はここで定義されています
  148 |         ll y, z;
      |               ^
main.cpp:150:32: 警告: ‘y’ may be used uninitialized [-Wmaybe-uninitialized]
  150 |                 return pll(0, 1);
      |                                ^
main.cpp:148:12: 備考: ‘y’ はここで定義されています
  148 |         ll y, z;
      |            ^

ソースコード

diff #

// 研究用ファイル

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>; using pii = pair<int, int>;
using vl = vector<ll>; using pll = pair<ll, ll>;

ll my_gcd(ll a, ll b) {
	a = abs(a); b = abs(b);
	if (a < b) swap(a, b);
	if (a == 0) return 0; // (0,0)

	// recursive
	if (b == 0) return a;
	// ll r = a % b;
	return my_gcd(b, a % b);

	// not recursive
	// while (b > 0) {
	// 	ll r = a % b; // ll q = a / b;
	// 	a = b;
	// 	b = r;
	// }
	// return a;
}

ll my_gcd(vl a) {
	ll g = 0;
	for (ll a_i : a) g = my_gcd(g, a_i);
	return g;
}

pll ext_gcd(ll _a, ll _b) {
	vl a = {abs(_a), abs(_b)};
	if (a[0] < a[1]) swap(a[0], a[1]);
	if (a[0] == 0) return pll(0, 0); // (0,0)
	else if (a[1] == 0) { // (a,0)
		ll x = 1, y = 0;
		if (abs(_a) < abs(_b)) swap(x, y);
		if (_a < 0) x = -x;
		if (_b < 0) y = -y;
		return pll(x, y);
	}

	int n = 2; // number of terms

	while (a[n - 1] > 0) {
		a.push_back(a[n - 2] % a[n - 1]);
		++n;
	}
	// for (ll r : a) cout << r << ", "; cout << endl;

	ll x = 0, y = 1;
	// printf("(x, y) = (%lld, %lld)\n", x, y);
	for (int i = n - 2; i >= 2; --i) {
		ll q = a[i - 2] / a[i - 1];
		ll temp_x = y;
		ll temp_y = x - q * y;
		x = temp_x;
		y = temp_y;
		// cout << q << endl; printf("(x, y) = (%lld, %lld)\n", x, y);
	}

	if (abs(_a) < abs(_b)) swap(x, y);
	if (_a < 0) x = -x;
	if (_b < 0) y = -y;

	// assert(_a * x + _b * y == my_gcd(_a, _b)); //

	return pll(x, y);
}

vl ext_gcd(vl a) {
	int n = a.size();
	vl x(n);
	ll g;
	if (n == 0) {
		return x;
	} else if (n == 1) {
		if (a[0] > 0) x[0] = 1;
		else if (a[0] < 0) x[0] = -1;
		return x;
	} else if (n >= 2) {
		tie(x[0], x[1]) = ext_gcd(a[0], a[1]);
		g = my_gcd(a[0], a[1]);
	}

	// cout << "g: " << g << endl;
	// cout << "x: "; for (int i = 0; i < n; ++i) cout << x[i] << ", "; cout << endl;
	
	for (int i = 2; i < n; ++i) {
		ll X, Y;
		tie(X, Y) = ext_gcd(g, a[i]);
		for (int j = 0; j < i; ++j) {
			x[j] *= X;
		}
		x[i] = Y;
		g = my_gcd(g, a[i]);
		// printf("(X, Y) = (%lld, %lld)\n", X, Y);
		// cout << "g: " << g << endl;
		// cout << "x: "; for (int i = 0; i < n; ++i) cout << x[i] << ", "; cout << endl;
	}

	return x;
}

// mod m での a の逆元の拡張: a * x = g = gcd(a, m) なる0 <= x < m
// a*x ≡ g mod m
// a*x + m*y ≡ g
ll my_inv(ll a, ll m) {
	assert(m >= 1);
	ll x = ext_gcd(a, m).first;
	if (x < 0) x += m;
	return x;
}


// 合同方程式 x ≡ r[i] mod m[i] の解を x ≡ y mod z として、(y,z)を返す
// m[i] >= 1
// n = 2
// g = gcd(m1,m2) = 1 のとき、
// m1 * x1 + m2 * x2 = 1 となるx1,x2を見つけ、
// x = r1*m2*x2 + r2*m1*x1 とすればよい
// g > 1 のとき、
// r1 ≡ r2 (≡ r0) mod g を前提として、
// s1 = (r1 - r0) / g, s2 = (r2 - r0) / g とする

pll my_crt(ll r1, ll r2, ll m1, ll m2) {
	assert(m1 >= 1); assert(m2 >= 1);
	ll g = my_gcd(m1, m2), l = m1 / g * m2;
	ll r = r1 % g;
	if ((r2 - r) % g != 0) return pll(0, 0);
	ll s1 = (r1 - r) / g, s2 = (r2 - r) / g;
	ll n1 = m1 / g, n2 = m2 / g;
	ll y1, y2;
	tie (y1, y2) = ext_gcd(n1, n2);
	ll y = (s1 * n2 * y2 + s2 * n1 * y1) % (l / g);
	// if (y < 0) y += l / g;
	ll x = (y * g + r) % l;
	if (x < 0) x += l;
	return pll(x, l);
}

pll my_crt(vl r, vl m) {
	int n = r.size();
	assert(m.size() == n);
	ll y, z;
	if (n == 0) {
		return pll(0, 1);
	} else if (n == 1) {
		assert(m[0] >= 1);
		ll y = r[0] % m[0], z = m[0];
		if (y < 0) y += z;
		return pll(y, z);
	} else if (n >= 2) {
		tie(y, z) = my_crt(r[0], r[1], m[0], m[1]);
	}
	for (int i = 2; i < n && z > 0; ++i) {
		tie(y, z) = my_crt(y, r[i], z, m[i]);
	}
	return pll(y, z);
}

// test

void test_my_gcd() { // ext_gcd
	ll a, b;
	a = rand(); if (rand() % 2) a = -a;
	b = rand(); if (rand() % 2) b = -b;
	cin >> a >> b;

	printf("(a, b) = (%lld, %lld)\n", a, b);
	printf("%lld %lld %lld\n", a, b, my_gcd(a, b));
	ll x, y; tie(x, y) = ext_gcd(a, b);
	printf("gcd(%lld, %lld) = %lld, (x, y) = (%lld, %lld)\n", a, b, my_gcd(a, b), x, y);
}

void test_my_gcd_multi() {
	vl a;
	int n;
	// n = rand() % 10;
	cin >> n;
	cout << n << endl;
	for (int i = 0; i < n; ++i) {
		// a.push_back(rand());
		int a_i; cin >> a_i;
		a.push_back(a_i);
	}
	for (int a_i : a) cout << a_i << ", "; cout << endl;
	cout << my_gcd(a) << endl;
}

void test_ext_gcd_multi() {
	int n;
	cin >> n;
	vl a(n);
	for (int i = 0; i < n; ++i) {
		ll a_i; cin >> a_i;
		a[i] = a_i;
	}
	vl x = ext_gcd(a);
	for (int x_i : x) cout << x_i << " "; cout << endl;
}

void test_my_inv() {
	ll a, m; cin >> a >> m;
	printf("%lld * %lld = %lld (mod %lld)\n", a, my_inv(a, m), my_gcd(a, m), m);
}

void test_my_crt() {
	int n;
	// cin >> n;
	n = 3;
	vl r(n), m(n);
	for (int i = 0; i < n; ++i) {
		cin >> r[i] >> m[i];
	}
	ll y, z; tie(y, z) = my_crt(r, m);
	if (z == 0) cout << -1 << endl;
	else cout << y << endl;

	// cout << y << " " << z << endl;
	// cout << y << endl;
}

int main() {
	srand((unsigned)time(NULL));

	// test_my_gcd();
	// test_my_gcd_multi();
	// test_ext_gcd_multi();
	// test_my_inv();
	test_my_crt();
}
0