• 2020 KAIST 10th ICPC Mock Contest部分题目解答


    题目链接 https://codeforces.com/gym/102760

    B

    首先计算出 Donghyun 可以抗 (t=lceil frac{c}{5} ceil) 次伤害。

    如果 t>b ,那就死不了,存活概率 (1)

    如果 t<=b ,总情况有 (C_a^b) 种, 而保证 Donghyun 死掉的情况有 (C_{a-b}^{b-t}) 种,故存活的概率为

    [1-frac{C_{a-b}^{b-t}}{C_a^b} = 1-prod_{i=1}^{t}frac{b-i+1}{a-i+1} ]

    代码:

    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    
    int a,b,c;
    int main(){
        cin>>a>>b>>c;
        int t=(c%5==0?c/5:c/5+1);
        if(t>b) cout<<1<<endl;
        else{
            long double ans=1;
            for(int i=1;i<=t;i++) ans=ans*(b-i+1)/(a-i+1);
            cout<<setprecision(10)<<1-ans<<endl;
        }
        return 0;
    }
    

    D

    记所求的值分别为 minv,maxv ,前者很好求,就是对排序,最小生成树就是用最短的 n-1 条边得到的,所得权值显然最小。

    但是后者并不能取最长的 n-1 条边,因为对应的最小生成树无法保证是用它们连成的。

    那么大致的思想是让比较小的边尽量组成完全图,这样它们就不足以得到生成树。

    具体来讲就是对边进行排序,(假设给了一个 (n) 阶完全图)然后先让小边组成 (n-1) 阶完全图,这样大边就可以选出最小的那条去得到生成树。
    这样一来,我们就可以按照这个策略下去,让小边按顺序组成 (1,2,3...n-1,n) 阶完全图。(可以用反证法证明没有更好的策略了。)

    那么生成树权值和就是由区间[1,1],[2,3],[3,6],...[(n-1)*(n-2)/2+1,n*(n-1)/2]中的最小值求和得来。

    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=100,M=N*N;
    int n;
    int a[M];
    
    int main(){
        cin>>n;
        FOR(i,1,n*(n-1)/2) cin>>a[i];
    
        sort(a+1,a+1+n*(n-1)/2);
        
        ll minv=0,maxv=0;
    
        FOR(i,1,n-1) minv+=a[i];
    
        int s=1;
        FOR(i,1,n-1)
        {
            s+=i-1;
            maxv+=a[s];
        }
    
        cout<<minv<<' '<<maxv<<endl;
        return 0;
    }
    

    F

    这题一眼看过去就是二分答案,枚举起点,然后二分求出相应起点对应正方形的边长最大值,不断更新就好了。
    在二分check的时候需要知道区间的最小值,故用ST表维护。

    总的时间复杂度是 (O(Nlog{N}))

    好像还可以用单调栈来做,时间复杂度是 (O(N)),但我不熟悉太弱了

    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=3e5+5,M=20;
    int a[N];
    int n;
    
    //st
    int st[N][M];
    int Log[N];
    void pre(){
        Log[1]=0;
        FOR(i,2,N-1) Log[i]=Log[i/2]+1;
    }
    
    void init(){
        FOR(j,0,M-1)
            for(int i=1;i+(1<<j)-1<=n;i++)
                if(!j) st[i][j]=a[i];
                else st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);
    }
    
    int query(int l,int r){
        int s=Log[r-l+1];
        return min(st[l][s],st[r-(1<<s)+1][s]);
    }
    
    //binary checker
    bool check(int cur,int len){
        return len<=query(cur,cur+len-1) && cur+len-1<=n;
    }
    
    int main(){
    
        cin>>n;
        FOR(i,1,n) cin>>a[i];
    
        //build st
        pre();
        init();
    
        int ans=1;
        FOR(i,1,n){
            int l=0,r=n;
            while(l<r){
                int mid=l+r>>1;
                if(check(i,mid+1)) l=mid+1;
                else r=mid;
            }
            ans=max(ans,l);
        }
    
        cout<<ans<<endl;
    
        return 0;
    }
    

    H

    一开始我还读错题意了,以为是贪心,事实上不是orz,这题就是一个暴力,枚举 六种物品 取与不取即可,共 (2^6) 种策略。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N=1e5+5;
    int v[7],a[N];
    int ans=0;
    int n,k;
    bool choose[64][7];
     // 记录策略
    int main(){
        cin>>n>>k;
        for(int i=1;i<=6;i++) cin>>v[i];
        for(int i=1;i<=n;i++) cin>>a[i];
    
        for(int i=0;i<(1<<6);i++){
            for(int j=1;j<=6;j++){
                choose[i][j]= (i>>j-1)&1;
            }
        }
    
        for(int i=0;i<(1<<6);i++){
            int t=k;
            int rec=0;
            for(int j=1;j<=n;j++){
                if(choose[i][a[j]] && t>=v[a[j]]){
     // 模拟能否选取,如果能则必须选。
                    t-=v[a[j]];
                    rec++;
                }
            }
            ans=max(ans,rec);
        }
        cout<<ans<<endl;
    
        return 0;
    }
    

    K

    构造题,可以先放在一维上思考,此时的策略是 ({1,2,3...,n-1,n,n-1,...3,2,1})

    推广到平面:
    想到将 (x坐标) 为第一关键字, (y坐标) 为第二关键字排序,尽量化为一条线处理,此时类似地连边即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N=1005;
    int n;
    struct node{
        int x,y;
        int id;
    }p[N];
    
    bool cmp(node a,node b){
        if(a.x<b.x) return true;
        if(a.x==b.x) return a.y<b.y;
        return false;
    }
    int main(){
        cin>>n;
    
        for(int i=1;i<=n;i++){
            cin>>p[i].x>>p[i].y;
            p[i].id=i;
        }
    
        sort(p+1,p+1+n,cmp);
    
        cout<<2*n-1<<endl;
        
        for(int i=1;i<=n;i++) cout<<p[i].id<<' ';
        for(int i=n-1;i;i--) cout<<p[i].id<<' ';
        cout<<endl;
    
        return 0;
    }
    
  • 相关阅读:
    TensorFlow Executor解析
    面试复习
    [洛谷]P1880 石子合并问题
    [西建大ACM协会]OJ平台如何使用
    [ACM] 相关OJ及在线运行代码网站
    [MySQL] Win10 安装MySQL5.7.27
    [PTA] PAT(A) 1012 The Best Rank (25 分)
    [PTA] PAT(A) 1011 World Cup Betting (20 分)
    [PTA] PAT(A) 1010 Radix (25 分)
    [PTA] PAT(A) 1009 Product of Polynomials (25 分)
  • 原文地址:https://www.cnblogs.com/Tenshi/p/14399257.html
Copyright © 2020-2023  润新知