• Educational Codeforces Round 17 ACD


    Educational Codeforces Round 17 ACD

    A. k-th divisor(暴力)

    链接
    题意:给出n和k,求出n的第k个因子 n ≤ 1 0 15 , k ≤ 1 0 9 n \le 10^{15},k \le 10^9 n1015,k109
    思路:直接 n \sqrt{n} n 的因数分解,特判1

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    signed main()
    {
        int n, k;
        cin >> n >> k;
        if (n == 1) {if (k == 1) cout << 1; else cout << -1; return 0;}
        vector<int> vec;
        for (int i = 1; i * i <= n; i++) {
            if (i * i == n && n % i == 0) {vec.push_back(i); break;}
            if (n % i == 0) vec.push_back(i), vec.push_back(n / i);
        }
        sort(vec.begin(), vec.end());
        if (k > vec.size()) {cout << -1;return 0;}
        cout <<vec[k - 1];
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    C. Two strings

    链接
    题意:给出字符串a和b,需要从b中删除一段连续的字符,使得b是a的子序列,要求最小化删除数量,求完成删除的b
    思路:因为要求完成删除的b,我们可以求一个b前缀对于a字子序列和b后缀对于a的子序列,前缀数组 l [ i ] l[i] l[i]的含义是在a在 i i i位置可以包含a的子序列的长度。然后因为要是的子序列并且最短,我们遍历a的前缀长度i,那么对于后缀,他包含的b需要比前缀的大,所以在遍历的时候用一个二分,就可以确定删除的区间,更新一个最小值就行

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N = 1e5+10;
    int l[N], r[N];
    char a[N], b[N];
    signed main()
    {
        cin >> (a + 1) >> (b + 1);
        int idx = 1;
        int lena = strlen(a + 1), lenb = strlen(b + 1);
        for (int i = 1 ; i <= lena; i++) {
            if (b[idx] == a[i]) {idx++;}
            l[i] = idx - 1;
        }
        idx = lenb;
        for (int i = lena; i >= 1; i--) {
            if (b[idx] == a[i]) {idx--;}
            r[i] = idx + 1;
        }
        r[lena + 1] = lenb + 1;
        int ansr = 0, ansl = 0, minn = 1e9;
        for (int i = 0; i < lena; i++) {
            int R = upper_bound(r + i + 1, r + 1 + lena, l[i]) - r;
            R = r[R];
            int L = l[i];
            if (R - L - 1 < minn) {
                ansr = R; ansl = L; minn = R - L - 1;
            }
        }
        int R = lenb + 1;
    	int L = l[lena];
    	if(R - L - 1 < minn) {
    		ansl = L;
    		ansr = R;
    	}
        for (int i = 1; i <= ansl; i++) cout << b[i];
        for (int i = ansr; i <= lenb; i++) cout << b[i];
        if (ansr > lenb && ansl < 1) {cout << '-';}
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    D. Maximum path(状态dp,推结论)

    链接
    题意:给出一个 3 ∗ n 3*n 3n的矩阵,可以往上下左右走,要求从 ( 1 , 1 ) (1,1) (1,1) ( 3 , n ) (3,n) (3,n)路径权值最小
    思路:最麻烦的是往左走,但是我们可以发现,任何往左走多步的状况都可以被只往左走一步或者一直上下右走替代,分成奇偶讨论,不方便画图,看情况补图把,然后接下来就是枚举状态了,我总共写了5种状态,分别是最后一步走在 ( 1 , i ) , ( 2 , i ) , ( 3 , i ) (1,i),(2,i),(3,i) (1,i),(2,i),(3,i),然后还有两个左走的情况,因为左走最后回到的地方一定是 ( 1 , i ) , ( 3 , i ) (1,i),(3,i) (1,i),(3,i),但是这时候会产生两列的代价,因为涉及到往回走,所以在算两种情况,根据5种情况凑一下dp
    洛谷
    图片来源洛谷

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int dp[1000010][5], a[4][1000010];
    signed main()
    {
        int n;
        cin >> n;
        for (int i = 1; i <= 3; i++) {
            for (int j = 1; j <= n; j++) cin >> a[i][j];
        }
        dp[1][0] = a[1][1];
       	dp[1][1] = a[1][1] + a[2][1];
       	dp[1][2] = dp[1][3] = dp[1][1] + a[3][1];
       	dp[1][4] = -0x3f3f3f3f3f3f3f3f;
       	for(int i = 2; i <= n; i++) {
       		dp[i][0] = max({dp[i - 1][0] + a[1][i], dp[i - 1][1] + a[1][i] + a[2][i], dp[i - 1][2] + a[1][i] + a[2][i] + a[3][i], dp[i - 1][4] + a[1][i] + a[2][i] + a[3][i]});
       		dp[i][1] = max({dp[i - 1][0] + a[1][i] + a[2][i], dp[i - 1][1] + a[2][i], dp[i - 1][2] + a[2][i] + a[3][i]});
       		dp[i][2] = max({dp[i - 1][0] + a[1][i] + a[2][i] + a[3][i], dp[i - 1][1] + a[2][i] + a[3][i], dp[i - 1][2] + a[3][i], dp[i - 1][3] + a[1][i] + a[2][i] + a[3][i]});
       		dp[i][3] = max(dp[i - 1][0] + a[1][i] + a[2][i] + a[3][i], dp[i - 1][3] + a[1][i] + a[2][i] + a[3][i]);
       		dp[i][4] = max(dp[i - 1][2] + a[1][i] + a[2][i] + a[3][i], dp[i - 1][4] + a[1][i] + a[2][i] + a[3][i]);
       	}
        cout << max({dp[n][2], dp[n][3]});
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    yolo系列模型训练数据集全流程制作方法(附数据增强代码)
    C语言之函数详解
    回溯框架总结
    大数据必学Java基础(七):扩展环境变量
    GitHub下载太慢的解决方案
    JavaScript-前端环境搭建-nodejs-打包分发-Webstorm-vue安装创建
    【X3m】opencv和opencv_contrib交叉编译
    Java并发线程池原理源码深入分析与调优实战
    一次偶然的钓鱼文件分析
    用C语言实现状态机设计模式
  • 原文地址:https://blog.csdn.net/qq_51672768/article/details/125434920