Problem:
Spreadsheet
問題
格子状のマス目があり、上端から行番号、左端から列番号が振られています。行番号と列番号の組によって、それぞれのマス目の位置を表します。また、隣り合う縦線同士、隣り合う横線同士の間隔はすべて $1$ です。
行の番号はアラビア数字、列の番号はアルファベット大文字からなる文字列で表され、以下のような規則で振られています。
行番号は $10$ 進法の整数値で
1
,
2
,
3
, $\dots$ , と続く
列番号はアルファベット $1$ 文字の列と $2$ 文字の列がある
$2$ 文字の列番号は $1$ 文字の列番号のあとである
A
から
Z
までは、辞書順に振られている
AA
から
ZZ
までは、辞書順に振られている
このマス目のいくつかを使って長方形が描かれています。この長方形の辺はすべてマス目の縦または横の線と平行で、$4$ つの頂点は格子点上にあります。この長方形の内部で左上のマスの列番号・行番号と右下のマスの列番号・行番号が与えられたとき、この長方形の面積を出力してください。
制約
$1 \leq |c1|, |c2| \leq 2$
$1 \leq r1, r2 \leq 99$
$c1, c2$ はアルファベットの大文字からなる
$r1, r2$ は整数
$r2$ は $r1$ と等しいか $r1$ よりあとにある
$c2$ は $c1$ と等しいか $c1$ よりあとにある
入力
入力は以下の形式で標準入力から与えられます。
$c1$ $r1$ $c2$ $r2$
左上のマスの列番号が $c1$ 、行番号が $r1$
右下のマスの列番号が $c2$ 、行番号が $r2$
出力
長方形の面積を $1$ 行に出力してください。
入力例 1
C 1 F 5
出力例 1
20
入力例 2
AZ 9 BI 30
出力例 2
220

Submitted solutions:

code_snippet: #include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

class edge {
public:
	int to, val;
	edge() : to(-1), val(-1) {};
	edge(int to_, int val_) : to(to_), val(val_) {};
};

int GCD(int x, int y) {
	if (y == 0) return x;
	return GCD(y, x % y);
}

int LCM(int x, int y) {
	return x / GCD(x, y) * y;
}

pair<int, int> solve(int N, vector<vector<edge> >& G) {
	int all_lcm = 1;
	for (int i = 0; i < N; i++) {
		for (edge e : G[i]) {
			all_lcm = LCM(all_lcm, e.val);
		}
	}
	vector<int> divs;
	for (int i = 1; i <= all_lcm; i++) {
		if (all_lcm % i == 0) {
			divs.push_back(i);
			if (i * i != all_lcm) {
				divs.push_back(all_lcm / i);
			}
		}
	}
	sort(divs.begin(), divs.end());
	int S = divs.size();
	vector<vector<bool> > vis(N, vector<bool>(S, false));
	vis[0][0] = true;
	queue<pair<int, int> > que;
	que.push(make_pair(0, 0));
	while (!que.empty()) {
		pair<int, int> u = que.front(); que.pop();
		for (edge e : G[u.first]) {
			int npos = lower_bound(divs.begin(), divs.end(), LCM(divs[u.second], e.val)) - divs.begin();
			if (!vis[e.to][npos]) {
				vis[e.to][npos] = true;
				que.push(make_pair(e.to, npos));
			}
		}
	}
	int al = (1 << 30), ar = -(1 << 30);
	for (int i = 0; i < S; i++) {
		if (vis[N - 1][i]) {
			al = min(al, divs[i]);
			ar = max(ar, divs[i]);
		}
	}
	return make_pair(al, ar);
}

int main() {
	int N, M;
	cin >> N >> M;
	vector<vector<edge> > G(N);
	for (int i = 0; i < M; i++) {
		int a, b, c;
		cin >> a >> b >> c; a--, b--;
		G[a].push_back(edge(b, c));
	}
	pair<int, int> res = solve(N, G);
	if (res.first <= res.second) {
		cout << res.first << ' ' << res.second << endl;
	}
	else {
		cout << "IMPOSSIBLE" << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 3884
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

long long GCD(long long a, long long b) {
	if (b == 0) return a;
	return GCD(b, a % b);
}

long long LCM(long long a, long long b) {
	return (a / GCD(a, b)) * b;
}

// 入力
int N, M;
int A[2009], B[2009], C[2009];
vector<pair<int, int>> G[1009];
bool visited[1009][1009];

// その他の変数
vector<long long> List;
int nex[1 << 20][21];

void Initialize() {
	// LCM の列挙
	for (int i = 0; i < (1 << 20); i++) {
		long long r = 1;
		for (int j = 0; j < 20; j++) {
			if ((i & (1 << j)) != 0) r = LCM(r, j + 1);
		}
		List.push_back(r);
	}
	sort(List.begin(), List.end());
	List.erase(unique(List.begin(), List.end()), List.end());

	// 次の番号を求める
	for (int i = 0; i < (int)List.size(); i++) {
		for (int j = 1; j <= 20; j++) {
			int pos1 = lower_bound(List.begin(), List.end(), LCM(List[i], j)) - List.begin();
			nex[i][j] = pos1;
		}
	}
}

int main() {
	// 入力・初期化
	cin >> N >> M;
	for (int i = 1; i <= M; i++) {
		cin >> A[i] >> B[i] >> C[i];
		G[A[i]].push_back(make_pair(B[i], C[i]));
	}
	Initialize();

	// 幅優先探索
	queue<pair<int, int>> Q;
	Q.push(make_pair(1, 0)); visited[1][0] = true;
	while (!Q.empty()) {
		int pos1 = Q.front().first;
		int pos2 = Q.front().second; Q.pop();
		for (pair<int, int> to : G[pos1]) {
			int cost = nex[pos2][to.second];
			if (visited[to.first][cost] == true) continue;
			visited[to.first][cost] = true;
			Q.push(make_pair(to.first, cost));
		}
	}

	// 出力
	long long AnsL = (1LL << 60), AnsR = -(1LL << 60);
	for (int i = 0; i < (int)List.size(); i++) {
		if (visited[N][i] == false) continue;
		AnsL = min(AnsL, List[i]);
		AnsR = max(AnsR, List[i]);
	}
	if (AnsL == (1LL << 60)) cout << "IMPOSSIBLE" << endl;
	else cout << AnsL << " " << AnsR << endl;
	return 0;
}
accuracy: 1
time_ms: 320
memory_kb: 13224
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr ll INF = 1001001001001001001LL;

struct edge {
    int to; ll cost;
};

ll lcm(ll a, ll b) {
    return a / __gcd(a, b) * b;
}

int main() {
    int n, m; cin >> n >> m;
    vector<vector<edge>> g(n);
    for(int i = 0; i < m; i++) {
        int a, b; ll c; cin >> a >> b >> c; a--; b--;
        g[a].push_back({b, c});
    }
    vector<set<ll>> reach(n);
    reach[0].insert(1);
    stack<pair<int, ll>> stk;
    stk.push({0, 1});
    while(!stk.empty()) {
        pair<int, ll> top = stk.top(); stk.pop();
        for(edge e : g[top.first]) {
            ll new_cost = lcm(top.second, e.cost);
            if(reach[e.to].count(new_cost)) continue;
            reach[e.to].insert(new_cost);
            stk.push({e.to, new_cost});
        }
    }
    ll mn = INF, mx = 0;
    for(ll cost : reach[n - 1]) {
        mn = min(mn, cost);
        mx = max(mx, cost);
    }
    if(mx == 0) cout << "IMPOSSIBLE\n";
    else cout << mn << ' ' << mx << '\n';
}
accuracy: 1
time_ms: 80
memory_kb: 11620
final_rank: 1