• X Samara Regional Intercollegiate Programming Contest DIV2


    http://codeforces.com/gym/101341

    其实我觉得这份题很不错的,虽然是div2,但是感觉对我挺有帮助(我比较垃圾0.0),还没补完(做的时候一直蒙逼,要补很多题)先写一点点的题解,后面的以后补上。

    A:

    B:这题有一个bug就是,当你一个"happiness"都没有的时候,你交换哪一个?如果随机输出的话是有bug的,就是比如你交换1和2,(注意都是要不同的pos),那么我构造ahppiness,就错了,交换后出现就不行了。所以还要自己处理一下。我是找有没有两个相同的字母,有就交换他们,就相当于没变了,没有的话,就不会出现"pp"和"ss",怎么交换都是成立的。

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 2e5 + 20;
    char str[maxn];
    char sub[] = "0happiness";
    int lensub;
    vector<int>pos[222];
    void work() {
        scanf("%s", str + 1);
        int lenstr = strlen(str + 1);
        int beOne = 0, enOne = 0, beTwo = 0, enTwo = 0;
        char ch[22] = {0};
        for (int i = 1; i <= lenstr; ++i) {
            for (int j = 1; j <= 8; ++j) ch[j] = ch[j + 1];
            ch[9] = str[i];
            pos[str[i]].push_back(i);
            if (strcmp(ch + 1, sub + 1) == 0) {
                if (beOne == 0) {
                    beOne = i - 8; enOne = i;
                    continue;
                }
                if (beTwo == 0) {
                    beTwo = i - 8; enTwo = i;
                    continue;
                }
                printf("NO
    ");
                return;
            }
        }
    //    printf("%d %d %d %d
    ", beOne, enOne, beTwo, enTwo);
        printf("YES
    ");
        if (!beOne && !beTwo) {
            for (int i = 'a'; i <= 'z'; ++i) {
                if (pos[i].size() >= 2) {
                    printf("%d %d
    ", pos[i][0], pos[i][1]);
                    return;
                }
            }
            printf("1 %d
    ", lenstr);
            return;
        }
        if (!beTwo) beTwo = 1;
        while (str[beTwo] == str[beOne]) beTwo++;
        printf("%d %d
    ", beOne, beTwo);
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        lensub = strlen(sub + 1);
        work();
        return 0;
    }
    View Code

    C:推公式貌似有点难度,做的时候一直想着推公式,分类讨论太乱了。然后吃了个饭回来想到可以二分答案。二分答案val,判定条件是:首先对于每一种求,最多只能拿Min(val, a + c)个,然后判断其是否> n,

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    LL a, b, c, n, m;
    bool check(LL val) {
        LL ra = min(val, a + c);
        LL rb = min(val, b + c);
        return ra <= n && rb <= m;
    }
    void work() {
        cin >> a >> b >> c >> n >> m;
        LL be = 0, en = a + b + c;
    //    cout << check(3) << endl;
        while (be <= en) {
            LL mid = (be + en) >> 1;
            if (check(mid)) be = mid + 1;
            else en = mid - 1;
        }
        cout << en << endl;
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

    D:签到题,对于一个数,可以向左跳或者向右跳,相当于可以加,可以减。回顾ax + by = c是否有整数解,只需要gcd(a, b) | c

    这是扩展欧几里德的内容,现在扩展到n个,一样的gcd即可。(比赛的时候还卡了这题,哭)

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    map<int, bool>vis, ans;
    const int maxn = 200000 + 20;
    int a[maxn], n;
    const int low = -1e9, high = 1e9;
    int x;
    
    void work() {
        scanf("%d%d", &n, &x);
        scanf("%d", a + 1);
        int gg = a[1];
        for (int i = 2; i <= n; ++i) {
            scanf("%d", a + i);
            gg = __gcd(gg, a[i]);
        }
        if (x % gg == 0) printf("YES
    ");
        else printf("NO
    ");
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

    E:这题我写得很复杂,也没看懂别人如何贪心,我是直接化公式,然后暴力segment tree维护。思路是,他从t1开始,首先把它左边的点都暴力走过去,因为没有其他方法了,然后,就是在[t1, t2]这段路上,选一个点(可能不选),走过去,然后走回t1传送去t2,然后从t2走去左边剩下的点,再走回来。一共花费的时间是,假如[t1, t2]这里有两个点pos[1], pos[2],那么花费的时间是,(pos[1] - t1) * 2 + (t2 - pos[2]) * 2 = 2 * (t2 - t1) + 2 * (pos[1] - pos[2]),所以应该选一个pos[i] - pos[i + 1]最小的去走,线段树维护。很复杂啦写的,

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 200000 + 20;
    #define root 1, m, 1
    #define lson L, mid, cur << 1
    #define rson mid + 1, R, cur << 1 | 1
    LL a[maxn], b[maxn];
    LL dis[maxn];
    LL mi[maxn << 2];
    void pushUp(int cur) {
        mi[cur] = min(mi[cur << 1], mi[cur << 1 | 1]);
    }
    void build(int L, int R, int cur) {
        if (L == R) {
            mi[cur] = dis[L];
            return;
        }
        int mid = (L + R) >> 1;
        build(lson);
        build(rson);
        pushUp(cur);
    }
    LL ask(int be, int en, int L, int R, int cur) {
        if (be > en) return inf + inf;
        if (L >= be && R <= en) {
            return mi[cur];
        }
        int mid = (L + R) >> 1;
        LL ans = inf + inf;
        if (be <= mid) {
            ans = ask(be, en, lson);
        }
        if (en > mid) {
            ans = min(ans, ask(be, en, rson));
        }
        return ans;
    }
    void work() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) cin >> a[i];
        for (int i = 1; i <= m; ++i) {
            cin >> b[i];
            if (i > 1) {
                dis[i - 1] = b[i - 1] - b[i];
            }
        }
        dis[m] = inf + inf;
        build(root);
        a[n + 1] = inf;
        LL sumTime = 0;
        int pb = 1, pa = 1;
        if (b[pb] <=  a[1]) {
            sumTime += 2 * (a[1] - b[pb]);
        }
        while (pb <= m && b[pb] <= a[1]) pb++;
        while (pb <= m) {
            if (pa == n) {
                sumTime += (b[m] - a[pa]) * 2;
                break;
            }
            if (a[pa + 1] <= b[pb]) {
                pa++;
                continue;
            }
            LL res1 = a[pa + 1] - a[pa];
            res1 = min(res1, (a[pa + 1] - b[pb]) * 2);
            if (b[pb + 1] <= a[pa + 1]) {
                res1 = min(res1, (b[pb] - a[pa]) * 2 + (a[pa + 1] - b[pb + 1]) * 2);
            } else res1 = min(res1, (b[pb] - a[pa]) * 2);
            int pos1 = lower_bound(b + 1, b + 1 + m, a[pa]) - b;
            int pos2 = upper_bound(b + 1, b + 1 + m, a[pa + 1]) - b;
            res1 = min(res1, (b[pos2 - 1] - a[pa]) * 2);
            pos2 -= 2;
    //        cout << dis[2] << endl;
    //        cout << ask(pos1, pos2, root) << endl;
            LL res3 = 2 * ask(pos1, pos2, root) + 2 * (a[pa + 1] - a[pa]);
    //        cout << res3 << endl;
            sumTime += min(res1, res3);
            pa++;
            while (pb <= m && b[pb] <= a[pa]) pb++;
        }
        cout << sumTime << endl;
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    View Code

    F:

    G:倒序模拟,一开始找1所在的位置pos, 设1喜欢的人是y[pos],然后就相当于找y[pos]那个人的名字,也是倒序模拟,直到找不到了,就直接输出那个人的名字就ok

    H:能证明的是,首先找到一个最大的数字val,在row,col中,这个数字是必定删除的,然后试试删除row,或者删除col,4种情况试一试就好。

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    typedef pair<int, int> pii;
    const int maxn = 1e3 + 20;
    int a[maxn][maxn];
    int n, m;
    pii findMax(int delRow, int delCol) {
        int mx = -1, row = -1, col = -1;
        for (int i = 1; i <= n; ++i) {
            if (i == delRow) continue;
            for (int j = 1; j <= m; ++j) {
                if (j == delCol) continue;
                if (mx < a[i][j]) {
                    mx = a[i][j];
                    row = i;
                    col = j;
                }
            }
        }
        return make_pair(row, col);
    }
    vector< pair<pii, int> >vc;
    int ansMx = inf;
    void dfs(int row, int col, int delRow, int delCol) {
        pii res = findMax(delRow, delCol);
        if (!row && !col) {
            vc.push_back(make_pair(make_pair(delRow, delCol), a[res.first][res.second]));
            if (ansMx > a[res.first][res.second]) {
                ansMx = a[res.first][res.second];
            }
            return;
        }
        if (row) {
            dfs(row - 1, col, res.first, delCol);
        }
        if (col) {
            dfs(row, col - 1, delRow, res.second);
        }
    }
    void work() {
        cin >> n >> m;
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                cin >> a[i][j];
            }
        }
        dfs(1, 1, 0, 0);
        for (int i = 0; i < vc.size(); ++i) {
            if (vc[i].second == ansMx) {
                cout << vc[i].first.first << " " << vc[i].first.second << endl;
                return;
            }
        }
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        IOS;
        work();
        return 0;
    }
    View Code

    I:这是一题神奇的题,其实这个东西我应该算学过,但是它换去矩阵了,所以就转不过来,思路是随机生成一个矩阵[1 X n]的矩阵,那么有rand * a * b = rand * c,这些复杂度才O(n^2),多随机几个,概率就满足了。这有点像那些米勒测试啊。

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 1e3 + 2;
    struct Matrix {
        int a[maxn][maxn];
        int row;
        int col;
        bool operator != (struct Matrix& rhs) const {
            for (int i = 1; i <= col; ++i) {
                if (a[1][i] != rhs.a[1][i]) return true;
            }
            return false;
        }
    }ans[4], c, cmp;
    struct Matrix matrix_mul(struct Matrix a, struct Matrix b, int MOD) { //求解矩阵a*b%MOD
    //    struct Matrix c = {0};  //这个要多次用到,栈分配问题,maxn不能开太大,
        //LL的时候更加是,空间是maxn*maxn的,这样时间用得很多,4和5相差300ms
        c.row = a.row; //行等于第一个矩阵的行
        c.col = b.col; //列等于第二个矩阵的列
        for (int i = 1; i <= c.row; ++i) for (int j = 1; j <= c.col; ++j) c.a[i][j] = 0;
        for (register int i = 1; i <= a.row; ++i) {
            for (register int k = 1; k <= a.col; ++k) {
                if (a.a[i][k]) { //应付稀疏矩阵,0就不用枚举下面了
                    for (register int j = 1; j <= b.col; ++j) {
                        c.a[i][j] = (c.a[i][j] + 1LL * a.a[i][k] * b.a[k][j]) % MOD;
                    }
                }
            }
        }
        return c;
    }
    void work() {
        srand((time(NULL)));
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= 3; ++i) {
            ans[i].row = ans[i].col = n;
            for (int j = 1; j <= n; ++j) {
                for (int k = 1; k <= n; ++k) {
                    scanf("%d", &ans[i].a[j][k]);
                }
            }
        }
        cmp.row = 1, cmp.col = n;
    //    cout << RAND_MAX << endl;
        for (int i = 1; i <= 25; ++i) {
            int upDate = rand();
            for (int k = 1; k <= n; ++k) {
                cmp.a[1][k] = rand() % 13131 + upDate;
            }
            Matrix res1 = matrix_mul(cmp, ans[1], 1e9 + 7);
            res1 = matrix_mul(res1, ans[2], 1e9 + 7);
            Matrix res2 = matrix_mul(cmp, ans[3], 1e9 + 7);
            if (res1 != res2) {
                printf("NO
    ");
                return;
            }
        }
        printf("YES
    ");
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        work();
        return 0;
    }
    666

    J:

    K:

    L:

    M:签到题,模拟即可。一个人优先杀最后那个。

  • 相关阅读:
    浅谈流形学习
    流形(Manifold)初步【转】
    MATLAB中的函数的归总
    LBP特征提取实现
    Nginx 安装
    Linux执行.sh文件,提示No such file or directory的问题
    Ubuntu 安装后的配置及美化(二)
    Ubuntu 安装后的配置及美化(一)
    关于windows上 web 和 ftp 站点的创建及使用
    win10 + Lubuntu 双系统安装
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6978062.html
Copyright © 2020-2023  润新知