Google APAC 2016 University Graduates Test Round A解題報告
注意到K最大是
GG = 10**19
sz = [0]
while sz[-1] < GG:
sz.append(sz[-1] * 2 + 1)
R = lambda: int(raw_input().strip())
T = R()
def solve(pos, kk):
assert(sz[pos] >= kk)
mid = sz[pos] / 2 + 1
if kk == mid: return 0
elif kk < mid: return solve(pos - 1, kk)
else:
kk -= mid
return 1 - solve(pos - 1, sz[pos - 1] - kk + 1)
for i in xrange(T):
print 'Case #' + str(i + 1) + ': ',
K = R()
print solve(len(sz) - 1, K)
B.gCube
將各個維度相乘就可以算出體積,對於目標長度,可以通過二分得到答案。我一開始沒注意到大資料會有乘法溢位的問題,導致大資料掛了,要不然就滿分了。。。解決浮點乘法溢位的辦法也很簡單:取對數。把乘法變成加法。
#include <bits/stdc++.h>
#define FOR(i, n) for (int i = 0; i < n; ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> point;
void solve() {
int N, Q, l, r;
cin >> N >> Q;
vector<double> arr(N);
FOR(i, N) cin >> arr[i];
FOR(i, Q) {
cin >> l >> r;
long double cur = 0.0;
for (int j = l; j <= r; ++j) {
cur += log(arr[j]);
}
long double low = 0.0, up = 1e10;
int cnt = 0;
while (cnt < 1000) {
++cnt;
long double mid = (low + up) / 2.0;
long double val = (long double)(r - l + 1) * log(mid);
if (val > cur) up = mid;
else low = mid;
}
cout << fixed << setprecision(10) << (low + up) / 2.0 << endl;
}
return;
}
int main() {
int TestCase;
cin >> TestCase;
FOR(caseID, TestCase) {
cout << "Case #" << caseID + 1 << ":" << endl;
solve();
}
return 0;
}
簡單來說,就是要求判斷一條邊是否有可能出現在最短路上,一個比較簡單的圖論題。首先通過floyd演算法求出所有點對之間的最短路徑,時間複雜度
distance(i, j) = distance(i, u) + w(u, v) + distance(v, j)
如果上式對於某個
#include <bits/stdc++.h>
#define FOR(i, n) for (int i = 0; i < n; ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> point;
const ll INF = (ll)1e14;
struct Edge {
int from, to, idx;
ll wei;
Edge(int _f, int _t, ll _w, int _i): from(_f), to(_t), wei(_w), idx(_i) {}
};
void solve() {
int n, m, x, y;
ll w;
scanf("%d %d", &n, &m);
vector<Edge> arr;
ll g[105][105];
FOR(i, n) FOR(j, n) {
if (i == j) g[i][j] = 0;
else g[i][j] = INF;
}
FOR(i, m) {
cin >> x >> y >> w;
g[x][y] = min(g[x][y], w);
g[y][x] = min(g[y][x], w);
arr.push_back(Edge(x, y, w, i));
}
ll dis[105][105];
FOR(i, n) FOR(j, n) {
dis[i][j] = g[i][j];
}
FOR(k, n) FOR(i, n) FOR(j, n) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
vector<bool> ok(m, false);
FOR(i, m) {
int f = arr[i].from, t = arr[i].to;
ll w = arr[i].wei;
FOR(j, n) FOR(k, n) {
if (ok[i] || dis[j][k] == dis[j][f] + w + dis[t][k]) {
ok[i] = true;
break;
}
}
if (!ok[i]) {
cout << i << endl;
}
}
return;
}
int main() {
int TestCase;
cin >> TestCase;
FOR(caseID, TestCase) {
cout << "Case #" << caseID + 1 << ":" << endl;
solve();
}
return 0;
}
一個看上去比較麻煩的模擬題,google每年都會出這種題目,關鍵在於要把思路理清楚,讓程式碼儘量簡潔一點,否則很容易出bug。
對於貪吃蛇的身體,由於每次只是頭部和尾部可能發生變化,因此只需要維護一個雙端佇列deque,每次向前移動,刪除尾部元素,更新頭部元素即可。
對於吃食物,可以用一個集合set來維護那些食物已經被吃過了,雖然總的食物點可能達到
對於判斷貪吃蛇是否因為碰到自己身體而死的情況,可以用雜湊表map來維護每個位置上的貪吃蛇身體數目,一旦發現一個位置上出現了超過一個貪吃蛇身體,就說明它碰到了自己的身體,遊戲結束。
最終程式碼只有80行。
#include <bits/stdc++.h>
#define FOR(i, n) for (int i = 0; i < n; ++i)
using namespace std;
typedef long long ll;
typedef pair<int, int> point;
typedef pair<int, char> rec;
const int dir_x[] = {1, 0, -1, 0};
const int dir_y[] = {0, -1, 0, 1};
set<point> eat;
inline bool has_food(point& pos) {
int cc = pos.first + pos.second;
if (cc % 2 == 0) return false;
if (eat.find(pos) != eat.end()) return false;
return true;
}
inline void eat_food(point& pos) {
eat.insert(pos);
}
void solve() {
int Q, row, col;
cin >> Q >> row >> col;
deque<point> snake;
eat.clear();
int d = 3, ptr = 0;
vector<rec> cmd(Q);
FOR(i, Q) cin >> cmd[i].first >> cmd[i].second;
sort(cmd.begin(), cmd.end());
map<point, int> visited;
snake.push_back({0, 0});
visited[{0, 0}] = 1;
int tt = 1;
while (true) {
if (tt > 1500000) {
cout << snake.size() << endl;
return;
}
point tp = snake.front();
tp.first = (tp.first + dir_x[d] + row) % row;
tp.second = (tp.second + dir_y[d] + col) % col;
if (!has_food(tp)) {
--visited[snake.back()];
if (visited[snake.back()] == 0) visited.erase(snake.back());
++visited[tp];
if (visited[tp] >= 2) {
cout << snake.size() << endl;
return;
}
snake.push_front(tp);
snake.pop_back();
}
else {
eat_food(tp);
++visited[tp];
if (visited[tp] >= 2) {
cout << snake.size() << endl;
return;
}
snake.push_front(tp);
}
if (ptr < cmd.size() && cmd[ptr].first == tt) {
if (cmd[ptr].second == 'L') d = (d - 1 + 4) % 4;
else {
d = (d + 1) % 4;
assert(cmd[ptr].second == 'R');
}
++ptr;
}
++tt; // increase clock
}
return;
}
int main() {
int TestCase;
cin >> TestCase;
FOR(caseID, TestCase) {
cout << "Case #" << caseID + 1 << ": ";
solve();
}
return 0;
}
第一次用markdown在csdn上寫部落格,請大家多指教。
也祝2016年畢業的童鞋拿到理想的offer,我參加這個筆試完全是for fun,對於被我擠掉名額的那個同學說一聲sorry。。。