- 寫在前面
- A
- B
- C
- D
- 寫在最後
寫在前面
比賽連結:https://codeforces.com/contest/1977
好久沒打了狀態拉了呃呃、、、最近被各種大學傻逼事兒搞得心力憔悴、、、整個週末渾渾噩噩地想爆肝一波又肝不動明明一直坐在電腦前兩天實際工作時間還不到 6h 發現狀態實在垃圾得一批於是決定把手上的最噁心的殺軟人工智慧實驗擺了,屬於是觸發熔斷機制了、、、然後感覺心情突然好了於是就打了這場。
傻逼大學能不能退學啊還有一週多就高考了我也不考了我直接會老家進輪胎廠去
A
簽到。
檢查運算元量是否足夠,若足夠檢查多餘的操作能否湊出 0 即可。
//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
//=============================================================
//=============================================================
//=============================================================
int main() {
//freopen("1.txt", "r", stdin);
std::ios::sync_with_stdio(0), std::cin.tie(0);
int T; std::cin >> T;
while (T --) {
int a, b; std::cin >> b >> a;
if (b >= a && (b - a) % 2 == 0) std::cout << "Yes\n";
else std::cout << "No\n";
}
return 0;
}
B
二進位制。
套路地先將 \(x\) 二進位制分解。發現題意要求不能有兩個連續位非 0,一個顯然的想法是考慮如何消去 \(x\) 中連續的 1。發現對於 \(x\) 中的一段連續的 1:\(2^{l}\sim 2^{r}\),可以轉換為 \(2^{r + 1} - 2^{l}\),僅需兩個位置變為非 0 即可。
然而經過上述轉化後,仍可能有相鄰兩個位置非 0,於是再進一步討論 \(a_i, a_{i + 1}\):
- \(a_i = a_{i + 1} \not= 0\):上述轉化後不可能出現,不需要考慮。
- \(a_{i} = -1, a_{i + 1} = 1\):令 \(a_{i} = 1, a_{i + 1} = 0\)。
- \(a_{i} = 1, a_{i + 1} = -1\):令 \(a_{i} = -1, a_{i + 1} = 0\)。
容易證明經過上述轉化後一定不會出現連續的非 0 位置,輸出此時各位即可。
實現時偷懶了直接每次詢問都輸出 32 位。
//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
//=============================================================
LL x, ans[40];
bool yes[40];
//=============================================================
//=============================================================
int main() {
//freopen("1.txt", "r", stdin);
std::ios::sync_with_stdio(0), std::cin.tie(0);
int T; std::cin >> T;
while (T --) {
std::cin >> x;
for (LL i = 0; i <= 31; ++ i) {
yes[i] = 0;
if (x >> i & 1) yes[i] = 1;
}
for (LL i = 0; i <= 31; ++ i) ans[i] = 0;
for (LL i = 0; i <= 31; ++ i) {
if (yes[i] == 1) {
int len = 0;
while (i <= 31 && yes[i] == 1) ++ i, ++ len;
ans[i - len] = -1, ans[i] = 1;
}
}
for (LL i = 0; i < 31; ++ i) {
if (ans[i] == -1 && ans[i + 1] == 1) {
ans[i + 1] = 0, ans[i] = 1;
}
if (ans[i] == 1 && ans[i + 1] == -1) {
ans[i + 1] = 0, ans[i] = -1;
}
}
std::cout << 32 << "\n";
for (int i = 0; i <= 31; ++ i) std::cout << ans[i] << " ";
std::cout << "\n";
}
return 0;
}
/*
0 0 0 0 1
0 -1 0 0 0
0 1 1 1 0
11
1 1 0 1
*/
C
數論。
先對 \(a\) 升序排序,然後特判答案是否為 \(n\),即判斷 \(\operatorname{lcm}_{1\le i\le n} a_i \not\in \{a_i\}\) 是否成立。若不成立,說明有 \(\operatorname{lcm}_{1\le i\le n} a_i = a_n\),即所有數均為 \(a_n\) 的因數。則此時任意子序列的 \(\operatorname{lcm}\) 均為 \(a_n\) 的因數。
於是列舉 \(a_n\) 的所有因數 \(d\) 檢查是否沒有在原數列中出現,且存在一個子序列滿足 \(\operatorname{lcm} = d\),即檢查數列中所有 \(d\) 的因數是否滿足 \(\operatorname{lcm} = d\)。
用 map
判斷權值是否出現,則總時間複雜度 \(O(n\sqrt{\max a}\log n)\) 級別。
//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
const int kN = 2010;
//=============================================================
int n, ans, a[kN];
std::map <LL, int> cnt;
//=============================================================
LL gcd(LL x_, LL y_) {
return y_ ? gcd(y_, x_ % y_) : x_;
}
LL lcm(LL x_, LL y_) {
return x_ / gcd(x_, y_) * y_;
}
void Check(LL d_) {
int nowans = 0;
LL nowlcm = 1;
for (int i = 1; i <= n; ++ i) {
if (a[i] == a[n]) break;
if (d_ % a[i] == 0) ++ nowans, nowlcm = lcm(nowlcm, a[i]);
}
if (nowlcm == d_) ans = std::max(ans, nowans);
}
void Solve() {
LL alllcm = 1;
for (int i = 1; i <= n; ++ i) {
alllcm = lcm(alllcm, a[i]);
if (alllcm > a[n]) {
ans = n;
break;
}
}
if (ans != n && !cnt.count(alllcm)) ans = n;
for (LL d = 1; d * d <= a[n]; ++ d) {
if (a[n] % d != 0) continue;
if (!cnt.count(d)) Check(d);
if (d * d != a[n] && !cnt.count(a[n] / d)) Check(a[n] / d);
}
}
//=============================================================
int main() {
// freopen("1.txt", "r", stdin);
std::ios::sync_with_stdio(0), std::cin.tie(0);
int T; std::cin >> T;
while (T --) {
std::cin >> n;
cnt.clear();
ans = 0;
for (int i = 1; i <= n; ++ i) {
std::cin >> a[i];
cnt[a[i]] = cnt[a[i]] + 1;
}
std::sort(a + 1, a + n + 1);
Solve();
std::cout << ans << "\n";
}
return 0;
}
D
guguug~
寫在最後
學到了什麼:
- C:先特判,考慮特判後是否等價於新增了什麼重要的條件。
我是廢物好相似啊傻逼大學