• AtCoder Beginner Contest ABC194题解


    考研选手为了ec-final开始复健(

    A题 I Scream

    注意需要将milk solids-not-fat和milk fat加起来就好了

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef pair<int, int > PII;
    const int N = 1e5 + 10;
    
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("my_in.txt", "r", stdin);
        freopen("my_out.txt", "w", stdout);
    #endif
        int a, b;
        scanf("%d %d", &a, &b);
        if(a + b >= 15 && b >= 8) cout<<1<<endl;
        else if(a + b >= 10 && b >= 3) cout<<2<<endl;
        else if(a + b >= 3) cout<<3<<endl;
        else cout<<4<<endl;
        return 0;
    }
    

    B题 Job Assignment

    由于N的范围很小只有一千,可以直接枚举一下
    做的时候没有管范围直接把A和B排了个序,判断一下A和B中的最小值是否来自同一个i,不是的话直接输出二者最大值,是的话就判断一下(max(A_1, B_2)和max(A_2, B_1)和A_1+B_1)三者哪个最小就好了

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef pair<int, int > PII;
    const int N = 1010;
    
    PII a[N], b[N];
    
    bool cmp(PII x, PII y){
        return x.first < y.first;
    }
    
    int main(){
        int n;
        cin>>n;
        for(int i = 0; i < n; i ++){
            scanf("%d %d", &a[i].first, &b[i].first);
            a[i].second = i, b[i].second = i;
        }
        sort(a, a + n, cmp);
        sort(b, b + n, cmp);
        if(a[0].second == b[0].second){
            int x = a[0].first + b[0].first;
            for(int i = 1; i < n; i ++){
                int y = max(b[i].first, a[0].first);
                if(y < x){
                    x = y; break;
                }
                else{
                    break;
                }
            }
            for(int i = 1; i < n; i ++){
                int y = max(a[i].first, b[0].first);
                if(y < x){
                    x = y; break;
                }
                else
                    break;
            }
            cout<<x<<endl;
        }
        else {
            cout<<max(a[0].first,b[0].first)<<endl;
        }
        return 0;
    }
    

    好像写了很傻的代码

    C题 Squared Error

    两种方法
    1.由于(|A_i| leq 200),可以将这3e5个数全部归到200以内,只用算这200个数的差平方再乘上每个数出现的次数。
    2.对题目中的公式进行推导,如下图
    process

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    const int maxn = 3e5 + 10;
    vector<int> a(maxn);
    
    int main(){
        int n;
        long long ans = 0, sum = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; i++){
            scanf("%d", &a[i]);
            sum += a[i];
            ans += a[i] * a[i];
        }
        ans *= n;
        ans -= sum * sum;
        cout<<ans<<endl;
        return 0;
    }
    

    D题 Journey

    是一道dp题
    假设当前有i个点已经连通,d[i]代表在此基础上要使图全部连通(即n个点都连通)时所需步数的期望。
    通过定义可知起始点为d[n] = 0,需从后往前推
    (d[i] = frac{n - i}{n}d[i+1] + frac{i}{n}d[i] + 1)
    也就是有两种状态可以转移至d[i],一种是从d[i+1]中减掉一个已经连通的点——选一个d[i]中未连通的点,所以是(n-i)/n * d[i+1],另一种是从d[i]选一个已连通的点,也就是i/n * d[i],最后再加上这一步的步数1。
    化简得到(d[i] = d[i+1] + frac{n}{n - i})

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e5 + 10;
    typedef long long ll;
    double a[N];
    
    int main(){
        int n;
        cin >> n;
        a[n] = 0.0;
        for(int i = n - 1; i > 0; i --){
            a[i] = a[i + 1] + (double)n / (double)(n - i);
        }
        printf("%.6lf
    ", a[1]);
        return 0;
    }
    

    E题 Mex Min

    求滑动区间最小mex值
    用类似滑动窗口做,将第一个区间算完后,将mex值看成从左往右从小到大的一行中第一个空着的地方。考虑几种情况:
    1.移出区间的值使mex左边空了一格,mex左移
    2.移出和新进区间的值正好相同,mex不变
    3.新进区间的值把mex的空填上了,需要继续往右找空的地方
    4.在mex的右边进行操作
    由于只需要求mex最小值,所以只考虑1的情况就可以了
    判断移出区间的值计数是否变为0,变为0则取当前mex和该值的最小值
    注意算第一个区间的时候,for循环要循环至max(Ai)+1

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1500010;
    int a[N], ct[N];
    
    int main(){
        int n, m, res = 1e9;
        scanf("%d %d", &n, &m);
        if(n == 1){
            cout<<1<<endl;
            return 0;
        } 
        for(int i = 0; i < n; i ++){
            scanf("%d", &a[i]);
            if(i < m)
                ct[a[i]] ++;
        }
        for(int i = 0; i <= n; i ++){
            if(ct[i] == 0){
                res = i;
                break;
            }  
        }
        for(int i = m; i < n ; i ++){
            int cnt = -1;
            ct[a[i - m]] --;
            ct[a[i]] ++;
            if(ct[a[i - m]] == 0)
                res = min(res, a[i - m]);
            if(res == 0){
                cout<<res<<endl;
                return 0;
            }
        }
        cout<<res<<endl;
        return 0;
    }
    

    F题明天补上~


    一以贯之的努力 不得懈怠的人生 每天的微小积累会决定最终结果 ————————裴之

    欢迎加我QQ:1136244161一起讨论,共同进步
  • 相关阅读:
    Webpack安装及基础配置
    相机拍到了光源的灯珠图像
    面向对象特殊用法
    面向对象初始
    内置函数和必须的模块
    模块基本模式
    函数三
    函数二
    装饰器
    函数初识
  • 原文地址:https://www.cnblogs.com/moomight/p/14559407.html
Copyright © 2020-2023  润新知