A. ConneR and the A.R.C. Markland-N
題目鏈接:https://codeforces.com/contest/1293/problem/A
題意:
有一個長為 n 的樓層,其中有 k 個樓層沒有餐廳 ,你現在在 s 層,問你最少走多少個樓層可以到達餐廳吃飯
分析:
因為 k 只有 1000,所以直接往 s 層上下方找(當找到 0 或者 n + 1 時說明這個方向沒有答案)
#include<bits/stdc++.h> using namespace std; #define ll long long map<ll , int>ha; int main() { int t; cin >> t; while(t --) { ha.clear(); ll n , s , k ; cin >> n >> s >> k; for(int i = 1 ; i <= k ; i ++) { int x; cin >> x; ha[x] = 1; } ll now = s , ans = (0x3f3f3f3f3f3fll); while(ha[now]) now ++ ; if(now != n + 1) ans = now - s; now = s; while(ha[now]) now --; if(now != 0) ans = min(ans , s - now); cout << ans << '\n'; } return 0; }
B. JOE is on TV!
題目鏈接:https://codeforces.com/contest/1293/problem/B
題意:
當敵人總數為 i 時,如果它犯了 j(j <= i) 個錯誤,則你可以獲得 $\dfrac {j}{i}$ 的報酬,同時敵人數量會減少 j 。現有n個敵人,問你能獲得的最大報酬為多少
分析:
(應該很很多人都是盲猜正解,比如我)
記敵人總數為 N , 若此時你要讓它犯 T 個錯誤,則你獲得的報酬為$\dfrac {T}{N}$ , 敵人總數變為 N - T。
但若你從 N 開始每次讓敵人犯1個錯誤直到敵人總數為 N - T , 那么的獲得的報酬就為 $\dfrac {1}{N}+\dfrac {1}{N-1}+\ldots +\dfrac {1}{N-T+1}$
然后可以證得 $\dfrac {T}{N}\leq \dfrac {1}{N}+\dfrac {1}{N-1}+\ldots +\dfrac {1}{N-T+1}$ (怎么證就不細說了)
所以每次只讓敵人犯一個錯誤獲得的報酬會是最大的
#include<bits/stdc++.h> using namespace std; int main() { int n ; double ans = 0; cin >> n; for(int i = 1 ; i <= n ; i ++) ans += 1.0 / i; cout << ans << '\n'; return 0; }
C. NEKO's Maze Game
題目鏈接:https://codeforces.com/contest/1293/problem/C
題意:
有一個 2 * N 的地圖,開始每個位置都是可以走的。然后地圖會改變 q 次,每次改變會使一個位置改變狀態(可走→不可走,不可走→可走)
問每次改變完地圖后是否能從(1 , 1)走到(2 , n)
分析:
因為地圖只有兩行,所以無法到達終點的情況只有這些:當前位置不可走,且該位置上、下、左上、左下、右上、右下不能走,我們用 cnt 統計這些情況的總個數
那么當 cnt = 0 時,則可以到達,否則不能
#include<bits/stdc++.h> using namespace std; #define ll long long const int N = 2e5 + 10; ll mat[10][N]; int main() { ll n , q , cnt = 0; cin >> n >> q; for(int i = 1 ; i <= q ; i ++) { ll x, y, z = 1; cin >> x >> y; if(x == 1) z = 2; if (mat[x][y]) cnt = cnt - mat[z][y - 1] - mat[z][y] - mat[z][y + 1]; else cnt = cnt + mat[z][y - 1] + mat[z][y] + mat[z][y + 1]; if (!cnt) cout << "Yes" << '\n'; else cout << "No" << '\n'; mat[x][y] ^= 1; } return 0; }
D. Aroma's Search
題目鏈接:https://codeforces.com/contest/1293/problem/D
題意:
有無數的點,第1個點的坐標為 (X1 , Y1) , 第2個點的坐標為 (X1 * ax + bx , Y1 * bx + by) , 第三個點的坐標為(X2 * ax + bx , Y2 * ay + by) ......
你的初始位置為(SX , SY) , 你每秒可以向上、向下、向左、向右移動一格。問在 T 秒內,你最多可以到達幾個點
分析:
題目給的 SX、SY、T 最大可取值都為 1e16 , 且點的個數是無限的,乍一看好像會有很多種情況,但因為ax , ay 都是大於等於2的,所以橫坐標和縱坐標的增長速率都大於等於 2 的冪次
而除第一個點外當橫坐標或縱坐標大於 1e17 時,這個點就肯定用不上了(因為此時這個點到距離它最近的點所用的時間必然 > T),那么算下來可以使用的點頂多也就60個.
所以我們可以枚舉一個起點和終點(枚舉的起點和終點可以相同)
若我們到達起點 i 所用的時間 + 從 i 到達終點 j 所用的時間小於等於T,則我們可以到達的點的個數為 $abs\left( i-j\right) +1$ (不理解可以把頂點的分布情況畫出來),然后更新一下 ans
// 比賽時用 dfs 枚舉的復雜度為O( n ^ 3 ) , 雖然不會超時但是寫的比較亂,所以賽后看tourist代碼改了一份精簡版的
#include<bits/stdc++.h> using namespace std; #define fi first #define se second #define ll long long const int N = 2e5 + 10; const ll MAXN = 1e17; vector<pair<ll , ll> >vec; ll dist(ll x1 , ll y1 , ll x2 , ll y2) { return abs(x1 - x2) + abs(y1 - y2); } int main() { ll x , y , ax , ay , bx , by; ll sx , sy , t; cin >> x >> y >> ax >> ay >> bx >> by; cin >> sx >> sy >> t; vec.push_back(make_pair(x , y)); while(1) { ll xx , yy , len = vec.size() - 1; if(vec[len].fi * 2 + bx < MAXN && vec[len].se * 2 + by < MAXN) xx = vec[len].fi * ax + bx , yy = vec[len].se * ay + by; else break; vec.push_back(make_pair(xx , yy)); } int ans = 0; for(int i = 0 ; i < vec.size() ; i ++) for(int j = 0 ; j < vec.size() ; j ++) if(dist(sx , sy , vec[i].fi , vec[i].se) + dist(vec[i].fi , vec[i].se , vec[j].fi , vec[j].se) <= t) ans = max(ans , abs(i - j) + 1); cout << ans << '\n'; return 0; }
E. Xenon's Attack on the Gangs
題目鏈接:https://codeforces.com/contest/1293/problem/E
待補
