• AtCoder Beginner Contest 215 A~F 题解


    本场链接:AtCoder Beginner Contest 215

    闲话

    感觉有些不在状态,傻逼题都做不出来,脑子想不进去.GH不知道能不能做,能做再说.

    A - Your First Judge

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    int main()
    {
        string s;cin >> s;
        if(s == "Hello,World!") cout << "AC
    ";
        else cout << "WA
    ";
        return 0;
    }
    
    

    B - log2(N)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    int main()
    {
        ll n;cin >> n;
        int res = 0;
        forn(k,0,62)    if((1ll << k) <= n) res = k;
        printf("%d
    ",res);
        return 0;
    }
    
    

    C - One More aab aba baa

    注意去重.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    const int N = 100;
    char s[N];
    int d[N];
    
    int main()
    {
        int k;scanf("%s%d",s + 1,&k);int n = strlen(s + 1);
        forn(i,1,n) d[i] = i;
    
        vector<string> all;
    
        do
        {
            string cur;
            forn(i,1,n) cur += s[d[i]];
            all.push_back(cur);    
        } while (next_permutation(d + 1,d + n + 1));
        
        sort(all.begin(),all.end());all.erase(unique(all.begin(),all.end()),all.end());
        cout << all[k - 1] << endl;
        return 0;
    }
    
    

    D - Coprime 2

    正难则反:考虑所有会有(gcd(a_i,k) = d)(d eq 1)(k).显然这样的(k)(a_i)的一个约数(d)的若干倍.那么枚举出所有(a_i)的约数,并且把这些约数自己和所有约数的倍数全部打上标记,被标记的点就是存在(gcd(a_i,k) = d)(d eq 1)(k).如此,统计最后没有被标记的数即可.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    const int N = 1e5+7;
    bool st[N];
    
    int main()
    {
        int n,m;scanf("%d%d",&n,&m);
        forn(i,1,n)
        {
            int a;scanf("%d",&a);
            for(int d = 1;1ll * d * d <= a;++d)
            {
                if(a % d != 0)  continue;
                st[d] = 1;
                st[a / d] = 1;
            }
        }
    
        st[1] = 0;
        
        forn(i,2,N - 1)
        {
            if(!st[i])  continue;
            for(int j = i;j <= N - 1;j += i)    st[j] = 1;
        }
    
        vector<int> res;
        forn(i,1,m) if(!st[i])  res.push_back(i);
    
        printf("%d
    ",(int)res.size());
        for(auto& _ : res)  printf("%d
    ",_);
        return 0;
    }
    
    

    E - Chain Contestant

    因为$ |sum| = 10$考虑状压:

    • (f[i][j][k])表示做完第(i)个位置,当前已经选出的元素集合是(j)且末尾元素是(k)的方案数.
    • 入口:(f[i][(1 << s_i)][s_i] = 1).
    • 转移:若不放入 (s_i) 显然 $ += f[i - 1][j][k]$ ;若放入 (s_i),可能会有两种情况:要么(s_i)是第一次出现在序列里,作为起点;要么(s_i)是接到当前已经有的屁股后面,显然这个已经有的必须是当前的末尾.如果是接到后面,让(f[i][j][k] += f[i - 1][j][k]),此时需要满足(k == j).反过来如果(k)不属于(j)集合,那么此时放入(s_i)就是作为一个新的起点:(f[i][j | (1 << s_i)][k] += sum_{z eq k} f[i - 1][j][z]).(在具体实现的时候,如果转移方程是正确的,那么(z == k)的时候也不会有问题,因为(j)里面不包含(k)的情况下方案数是(0))
    • 出口:(res = sum_{j,k} f[n][j][k]).

    入口可以不直接写出,在转移时给加一即可.

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    
    const int N = 10,M = (1 << 10),C = 1020,MOD = 998244353;
    int f[C][M][N];
    char s[C];
    
    int main()
    {
        int n;scanf("%d",&n);
        scanf("%s",s);
    
        forn(i,1,n)
        {
            int x = s[i - 1] - 'A';
            forn(j,0,(1 << 10) - 1) forn(k,0,9)
            {
                f[i][j][k] = f[i - 1][j][k];
                if(k == x)  f[i][j][k] = (1ll * f[i][j][k] + f[i - 1][j][k]) % MOD;
            }
            
            forn(j,0,(1 << 10) - 1)
            {
                if(j >> x & 1)  continue;
                forn(k,0,9) f[i][j | (1 << x)][x] = (1ll * f[i][j | (1 << x)][x] + f[i - 1][j][k]) % MOD;
            }
    
            f[i][1 << x][x] = (f[i][1 << x][x] + 1) % MOD;
        }
    
        int res = 0;
        forn(j,0,(1 << 10) - 1) forn(k,0,9)  res = (res + f[n][j][k]) % MOD;
        printf("%d
    ",res);
        return 0;
    }
    
    

    F - Dist Max 2

    使最小值最大,考虑二分答案:二分最终答案(ans geq L)?

    (ans geq L) 等价于 (min(|x_i - x_j|,|y_i - y_j|) geq L),即 (|x_i - x_j| geq L,|y_i - y_j| geq L) 同时满足.

    如此,check函数等价于求解:对于每个位置 (i in [1,n - 1]),是否存在一个 (j in [i + 1,n]) 同时满足如上两个条件.如果把绝对值拆掉,可以得到四个不等式,满足其中一个不等式即可.由于((i,j))的相对次序可以忽略,可以将所有点按照 (x) 坐标上升排序,这样可以删掉其中两个,最后剩下: (x_j - x_i geq L && y_i - y_j geq L)(x_j - x_i geq L && y_j - y_i geq L) 满足其一即可.

    排序之后保证了一维偏序关系,剩下的一维偏序关系可以发现只需要找到:在某个后缀中(y)的最大值或最小值,因为要看是否存在一个 (j in [i + 1,n]) 满足 (y_j - y_i geq L) 那肯定取 (y_j) 的最大值.分别记作 (Rmin/Rmax).即可将 check 的复杂度做到 (O(nlogn)).

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    #define forn(i,x,n) for(int i = x;i <= n;++i)
    #define forr(i,x,n) for(int i = n;i >= x;--i)
    #define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
    #define x first
    #define y second
    
    const int N = 2e5+7;
    pii p[N];
    int Rmin[N],Rmax[N];
    int n;
    
    bool check(int L)
    {
        forn(i,1,n - 1)
        {
            int pos = lower_bound(p + i + 2,p + n + 1,pii{p[i].x + L,0}) - p;
            if(pos == n + 1)    continue;
            if(Rmax[pos] >= L + p[i].y || Rmin[pos] <= p[i].y - L)  return 1;
        }
        return 0;
    }
    
    int main()
    {
        scanf("%d",&n);
        forn(i,1,n) scanf("%d%d",&p[i].x,&p[i].y);
        sort(p + 1,p + n + 1);
    
        Rmin[n] = p[n].y;Rmax[n] = p[n].y;
        forr(i,1,n - 1) Rmin[i] = min(Rmin[i + 1],p[i].y),Rmax[i] = max(Rmax[i + 1],p[i].y);
    
        int l = 0,r = 2e9,idx = 0;
        while(l < r)
        {
            int mid = l + r + 1 >> 1;
            if(check(mid))  l = mid;
            else r = mid - 1;
        }
        printf("%d
    ",l);
        return 0;
    }
    
    
  • 相关阅读:
    阿里云能耗宝助力华聚公司实现产品绿色升级
    最佳实践|从Producer 到 Consumer,如何有效监控 Kafka
    漫画 | 新一代软件架构会影响到谁?
    MongoDB :第七章:总结一下学习MongoDB的心得
    面试:第十二章:所有总结
    技术汇总:第十二章:技术总览
    接口文档:第二章:使用Swagger接口的文档在线自动生成
    为何你炒的肉又硬又柴?原来是忽略了关键1步,大厨教你正确做法
    IKEA bugs All In One
    Korean Keyboard All In One
  • 原文地址:https://www.cnblogs.com/HotPants/p/15173207.html
Copyright © 2020-2023  润新知