Codeforces Round #815 (Div. 2)

\(\quad\)早晨去吃饭时,被一个挺漂亮的女生打了招呼,我礼貌地回应你好。返程时,又被一个挺阳光的男生招呼,我也微笑挥手。可笑的是,这两个人,我都认不出是谁……然后就是大学的第一节高数,简单得离谱。虽然我安慰自己毕竟第一节课嘛,水点没事的,可当我翻遍了武大版的高数,深吸一口气,不妙,这也基础过分了吧不是凡尔赛,毕竟以前自学时听信某乎上面的建议看的基本都是纯英文的,还以为国外教材普遍浅显等正式上课会费力的。看来,即使到了大学,数学也还得自学。可不知怎么的忽然想起高二时一个晚上,与一个好友聊了很久。不久他靠信竞保送数学系后,已经三年,如今已是久未联系,也再没这个必要。人与人的差距,觉察时已似身陷泰坦尼克号,于命运的间隙凝视极寒的流川。想起初二躲被窝看\(MIT\)微积分公开课的时光,都忘了是什么时候放下做数学家的梦想了。
\(\qquad\)走走停停,兜兜转转,当寻常的一天成了过去,却是最致命的毒药。
\(\qquad\)把岁月留给岁月吧,好好学习,别管脸皮。
\(\qquad\)在图书馆借了两本难度大点的题集,依我的数学水平,一周不到就可以刷完,可对于今天,也只是平常的一天。

  • A

贪心

$code$
/*
a d = b c

if(a d = b c) -> 0
a * d < b * c

b * c / a * d

ans <= 2
*/
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif 
    int tt;
    cin >> tt;
    auto gcd = [&](long long a, long long b) -> long long {
        while(b ^= a ^= b ^= a %= b);
        return a;
    };
    while(tt--) {
        vector<long long> a(5);
        for(int i = 1; i <= 4; ++i) cin >> a[i];
        long long d1 = gcd(a[1], a[2]), d2 = gcd(a[3], a[4]);
        a[1] /= d1, a[2] /= d1;
        a[3] /= d2, a[4] /= d2;
        long long s1 = a[1] * a[4], s2 = a[2] * a[3];
        // cout << "[" << a[1] << " " << a[2] << " " << a[3] << " " << a[4] << "\n";
        // cout << "[s1 = " << s1 << " , " << "s2 = " << s2 << "]\n";
        if(s1 == s2) {
            cout << "0\n";
            continue;
        }
        if(s1 < s2) swap(s1, s2); // make sure s1 >= s2
        if((s1 == 0 || s2 == 0) || s1 % s2 == 0) cout << "1\n";
        else cout << "2\n";
        // cout << ans << "\n";
    }
    return 0;
}
  • B

把最大,次大,最小,次小标记下来,圈中间的两个

$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
    int tt;
    cin >> tt;
    while(tt--) {
        int n;
        cin >> n;
        int mx_1 = 0, mx_2 = 0, mn_1 = 1e9, mn_2 = 1e9;

        for(int i = 1; i <= n; ++i) {
            int x;
            cin >> x;
            if(x >= mx_1) {
                mx_2 = mx_1;
                mx_1 = x;
            }
            else if(x > mx_2) {
                mx_2 = x;
            }
            if(x <= mn_1) {
                mn_2 = mn_1;
                mn_1 = x;
            }
            else if(x < mn_2) {
                mn_2 = x;
            } 
        }
        
        // cout << "[" << mx_1 << ", " << mx_2 << ", " << mn_1 << ", " << mn_2 << "]\n";
        cout << mx_1 + mx_2 - mn_1 - mn_2 << "\n";
    }
    return 0;
}
  • C

到后期一\(L\)只切1个,考虑下前期不同情况处理的答案即可

$code$
# include "bits/stdc++.h"
using namespace std;
char str[503];
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
    int tt;
    cin >> tt;
    while(tt--) {
        int n, m;
        cin >> n >> m;
        // vector<char> str(m + 1);
        vector a(n + 1, bitset<503>());
        int ans = 0;
        for(int i = 1; i <= n; ++i) {
            // cin >> (str + 1);
            scanf("%s", str + 1);
            // cin >> str;
            for(int j = 1; j <= m; ++j) {
                a[i][j] = str[j] ^ '0';
                if(a[i][j] == 1) ++ans;
            }
        }
        // for(int i = 1; i <= n; ++i) {
        //     for(int j = 1; j <= m; ++j) {
        //         cout << a[i][j];
        //     }
        //     cout << "\n";
        // }
        // exit(0);
        int minn = 4;
        for(int i = 1; i < n; ++i) {
            for(int j = 1; j < m; ++j) {
                int tot = a[i][j] + a[i + 1][j] + a[i + 1][j + 1] + a[i][j + 1];
                minn = min(minn, max(1, tot - 1));
            }
        }
        if(ans == 0) {
            cout << "0\n";
        }
        else {
            cout << ans - minn + 1 << "\n";
        }
    }
    return 0;
}
  • D1

\(DP\)方程显然,优化时想到既然\(n<200\),那数位上就能很大幅度地排除遍历数目

$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
    int tt;
    cin >> tt;
    while(tt--) {
        int n;
        cin >> n;
        vector<int> a(n);
        vector<int> f(n, 1);
        for(int i = 0; i < n; ++i) {
            cin >> a[i];
        }
        for(int i = 0; i < n; ++i) {
            for(int j = max(i - 255, 0); j < i; ++j) {
                if((a[i] ^ j) > (a[j] ^ i)) {
                    f[i] = max(f[i], f[j] + 1);
                }
            }
        }
        cout << *max_element(f.begin(), f.end()) << "\n";
    }
    return 0;
}
  • D2

首先,如果\(a[i] \oplus j = a[j] \oplus i\),那么有\(a[i] \oplus i = a[j] \oplus j\)
\(D1\)出发,依然倚靠数位缩减遍历次数,而\(trie\)树可以很好处理数位,对每个新点,每次查询合法的最大值来传递,再上传入\(trie\)

$code$
# include "bits/stdc++.h"
using namespace std;
const int N = 3e5 + 3;
int t[N * 31][2], f[N * 31][2];
# define bit(x,i) ((x) >> (i) & 1)
int main() {
# ifdef T
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
    int tt;
    cin >> tt;
    while(tt--) {
        int n;
        cin >> n;
        vector<int> a(n);
        vector<int> ans(n);
        for(int i = 0; i < n; ++i) cin >> a[i];
        int trie_index = 0;
        for(int i = 0; i < n; ++i) {
            int u = 0, mx = 0, x = a[i] ^ i;
            for(int j = 30; j >= 0; --j) {
                int v = bit(x, j);
                if(t[u][v ^ 1]) {
                    mx = max(mx, f[t[u][v ^ 1]][bit(a[i], j) ^ 1]);
                }
                if(!t[u][v]) break;
                u = t[u][v];
            }
            ans[i] = mx + 1;
            u = 0;
            for(int j = 30; j >= 0; --j) {
                int v = bit(x, j);
                if(!t[u][v]) t[u][v] = ++trie_index;
                u = t[u][v];
                f[u][bit(i, j)] = max(f[u][bit(i, j)], ans[i]);
            }
        }
        for(int i = 0; i <= trie_index; ++i) t[i][0] = t[i][1] = f[i][0] = f[i][1] = 0;
        cout << *max_element(ans.begin(), ans.end()) << "\n";
    }
}
posted @ 2022-09-06 00:25  邱涵的秘密基地  阅读(45)  评论(0编辑  收藏  举报