Codeforces Round #704 (Div. 2) A~E
比賽連結:https://codeforces.com/contest/1492
1492A.Three swimmers
題意:
有三名游泳的人,他們分別需要 \(a,b,c\) 分鐘才能在一個游泳池遊一個來回,第一個游泳者將在開始時間 \(0,a,2a,3a,…\) 分鐘後在游泳池的左側,第二個游泳者將在 \(0,b,2b,3b,…\) 分鐘後,第三個將在 \(0,c,2c,3c,…\) 分鐘後出現在池的左側。
\(p\) 分鐘後最少需要等待多長時間會有一個游泳者到達游泳池左側。
思路:
簽到題,
可以暴力遍歷 \(a,b,c\) 尋找最小值,
也可以直接找 \(a,b,c\) 的倍數離 \(p\) 差多少
注意開 long long
....
【AC Code】
int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int _; for (cin >> _; _--;) { ll p, a, b, c; cin >> p >> a >> b >> c; if (p % a == 0 || p % b == 0 || p % c == 0) cout << "0\n"; else cout << min(a - p % a, min(b - p % b, c - p % c)) << "\n"; } }
1492B. Card Deck
題意:
有 \(n\) 張卡,每張卡的值 \(1\sim n\),等於 \(p_i\),\(p_1\) 代表底卡,\(p_n\) 是頂卡,在每個步驟中,選擇一些 \(k > 0\) 的整數,從原始卡片組中取出前 \(k\) 張卡片,然後按它們現在的順序將它們放置在新卡片組的頂部。讓階數最大。
思路:
找最大的數輸出最大的數加後邊的所有數,接著找第二個······注意不要重複輸出
【AC Code】
const int N = 1e5 + 10; ll a[N], pos[N]; bool st[N]; int main() { ios::sync_with_stdio(false), cin.tie(nullptr); int _; for (cin >> _; _--;) { vector<int>A; int n; cin >> n; for (int i = 1; i <= n; ++i) { cin >> a[i]; pos[i] = i; st[a[i]] = 0; } ll t = n; for (ll i = n; i >= 1; i -= 1) { if (a[i] == t) for (ll j = i; !st[a[j]] && j <= n; j += 1) { st[a[j]] = 1; A.emplace_back(a[j]); } while (st[t] && t >= 1) t -= 1; } for (ll i = 0; i < n; i += 1) cout << A[i] << " \n"[i == n - 1]; } }
1492C. Maximum width
題意:
給你兩個字串 \(s,t\) 找 \(s\) 串和 \(t\) 串匹配的下標,然後找相鄰下標之間的最大值,管你懂不懂看樣例就完事了
思路:
看了半天樣例發現只需要前後掃一遍,分別用兩個陣列去存前後掃的下標結果,取兩個陣列相鄰位置的最大值
【AC Code】
const int N = 2e5 + 10;
int n, m, a[N], b[N];
string s, t;
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cin >> n >> m >> s >> t;
int i = 0, j = 0;
while (j < m) {
if (s[i] == t[j]) {
a[j] = i + 1;
i ++; j ++;
} else i ++;
}
i = n - 1, j = m - 1;
while (j > 0) {
if (s[i] == t[j]) {
b[j] = i + 1;
i --; j --;
} else i --;
}
int ans = 0;
for (int q = 0; q < m; q ++)
ans = max(ans, b[q + 1] - a[q]);
cout << ans << "\n";
}
1492D. Genius’s Gambit
題意:
給你三個數,\(a\) 代表 \(0\) 的個數,\(b\) 代表 \(1\) 的個數,\(k\) 代表 \(x-y\) 中 \(1\) 的個數,讓你求出 \(x,y\) 滿足 \(a,b,k\) 三個條件,如果沒有輸出 NO
思路:
構造題,說實話賽時沒構造出來,這裡參考了一下題解
由題目可知 \(x>y\) 是肯定的,所以我們不妨假設 \(x,y為11…00…\) ,然後對 \(y\) 進行變換,我們發現 \(y\) 最右邊的1往後移動一位 \(x-y\) 的值就多一個 \(1\) ,最大為 \(a\) ,然後移動倒數第二個 \(1\) ,發現只能移動一次,如果移動兩次不會多一個 \(1\) 。
假設
x 1110000
y 1110000當 \(y\) 的倒數第一個 \(1\) 往右移動時發現 \(x-y\) 中 \(1\) 的個數 \(+1\) ,當y 1100001時 \(x-y\) 中 \(1\) 的個數為 \(4\) ,然後移動倒數第二個 \(1\),移動一次,發現 \(x-y\) 中 \(1\) 的個數變成了 \(5\) ,再移動一次發現又變回 \(4\) ,所以除了倒數第一個 \(1\) 可以移動多次,第一個 \(1\) 不能移動中間的 \(1\) 只能移動一次,我們可以找出規律,最大的值為 \(a+b-2\) 。
【AC Code】
int a, b, k;
int main(void) {
cin.tie(0);
ios::sync_with_stdio(false);
cin >> a >> b >> k;
if (k == 0) {
cout << "Yes" << '\n';
string x = "", y = "";
x += '1';
b--;
for (int i = 0; i < a; i++) x += '0';
for (int i = 0; i < b; i++) x += '1';
cout << x << '\n';
cout << x << '\n';
return 0;
}
k--;
if (a > 0 && b >= 2 && (a + b - 3 >= k)) {
cout << "Yes" << '\n';
string x = "";
string y = "";
a--; b -= 2;
x += '1'; y += '1';
x += '1'; y += '0';
for (int i = 0; i < k; i++) {
if (a) {
a--;
x += '0'; y += '0';
} else {
b--;
x += '1'; y += '1';
}
}
x += '0'; y += '1';
while (a--) {
x += '0'; y += '0';
}
while (b--) {
x += '1'; y += '1';
}
cout << x << '\n';
cout << y << '\n';
} else
cout << "No" << '\n';
}
模擬構造,我不會(QAQ
1492E. Almost Fault-Tolerant Database
題意:
給定 \(n\) 個長度為 \(m\) 的陣列,需要輸出一個長度為 \(m\) 的陣列,使得這些陣列之間不同的數不超過兩個,輸出YES,輸出你構造的陣列,若有多種情況,可任意輸出一種。如若不存在,輸出NO。
思路:
假設第一個陣列為標準陣列,遍歷
- 不同數小於等於 \(2\),沒問題
- 不同數大於 \(4\) ,直接輸出NO
- 就是 \(3,4\) 的情況,我們找差異數最大的那個也就是 \(4\) 的情況,列舉修改的兩個位置,判斷是否可以成立。
【AC Code】
const int N = 250010;
int n, m;
vector <int> s[N];
bool check2(vector<int> &v) {
for (int i = 1; i < n; i ++) {
int cnt = 0;
for (int j = 0; j < m; j ++)
if (s[i][j] != v[j]) cnt ++;
if (cnt > 3) return false;
else if (cnt == 3) {
int ans = 1;
for (int j = 0; j < m; j ++) {
if (s[i][j] != v[j] && v[j] == -1) {
ans = 0;
v[j] = s[i][j];
break;
}
}
if (ans) return false;
}
}
return true;
}
bool check() {
int cnt = 0, ax = 0, id;
for (int i = 1; i < n; i ++) {
int ans = 0;
for (int j = 0; j < m; j ++)
if (s[i][j] != s[0][j]) ans ++;
if (ans > 4) return false;
if (ans <= 2) cnt ++;
if (ans > ax)ax = ans, id = i;
}
if (cnt == n - 1) {
cout << "Yes\n";
for (int i = 0; i < m; ++i) cout << s[0][i] << " \n"[i == m - 1];
return true;
}
vector<int> a;
for (int i = 0; i < m; i ++)
if (s[0][i] != s[id][i]) a.push_back(i);
for (int i = 0; i < a.size(); i ++) {
for (int j = 0; j < a.size(); j ++) {
if (i == j) continue;
vector<int> b = s[0];
b[a[i]] = s[id][a[i]];
b[a[j]] = -1;
if (check2(b)) {
cout << "Yes\n";
for (int i = 0; i < m; ++i) cout << (b[i] == -1 ? s[0][i] : b[i]) << " \n"[i == m - 1];
return true;
}
}
}
return false;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
cin >> n >> m;
for (int i = 0; i < n; i ++) {
for (int j = 0, x; j < m; j ++) {
cin >> x;
s[i].push_back(x);
}
}
if (!check()) puts("No");
}
The desire of his soul is the prophecy of his fate
你靈魂的慾望,是你命運的先知。