zoukankan      html  css  js  c++  java
  • ABC135记录

    date: 2019-07-28

    A - Harmony

    题目大意:

    给你两个不同的整数AB,要求你找到一个整数K,同时满足|A-K|=|B-K|。找不到时,输出"IMPOSSIBLE"

    题目做法:

    聪明的读者读到这里肯定已经发现了,这其实就是平均数,但是,要特判AB的差是奇数的情况:此时K不是整数,所以输出"IMPOSSIBLE"

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int a,b;
    
    int main(){
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        cin>>a>>b;
        if((a+b)%2){//K不是整数
            cout<<"IMPOSSIBLE"<<endl;
        }else{
            cout<<(a+b)/2<<endl;
        }
    
        return 0;
    }
    

    B - 0 or 1 Swap

    题目大意:

    有一个长度为N的序列,内部元素为1~N。允许最多交换一次任意一对元素的位置,把这个序列变为升序(从小到大的)序列(可以选择不交换也就是交换零次,但最多一次),可以就输出"YES",否则输出"NO"

    题目做法:

    暴力。由于这道题的数据范围很小,所以只要模拟交换元素就好。

    我们跑一个二重循环代表交换的元素对,再在里面写一个循环判断是否有序即可。特殊地,我们需要直接判断这个序列是否有序,因为题目里说可以不交换。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int n;
    int a[55];
    
    bool chk(){//检查序列是否有序
        for(int i=1;i<=n;i++){
            if(a[i]<=a[i-1]){//其实因为是1~n的序列,可以直接写a[i]!=i判断
                return false;
            }
        }
        return true;
    }
    
    int main(){
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        for(int i=1;i<n;i++){
            for(int j=i+1;j<=n;j++){
                swap(a[i],a[j]);//模拟交换位置
                if(chk()){//有序了就输出
                    cout<<"YES"<<endl;
                    return 0;
                }
                swap(a[i],a[j]);//check完记得换回来
            }
        }
        if(chk()){//特殊地,判断数组一开始就有序的情况
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    
        return 0;
    }
    

    C - City Savers

    题目大意:

    N+1座城市,然后其中的第i个城市有A[i]个怪兽在,有N个英雄,第i个英雄可以打败在第ii+1城市的怪兽,但第i位英雄打败的怪兽不超过B[i]个。

    题目做法:

    贪心显然地,由于第i位英雄只能影响第ii+1城市,所以i之前的城市这位英雄都不能影响,所以尽量让第i位英雄打败第i座城市里的怪物,打不完B[i]个在去下一座城市。

    如果第i位英雄优先击杀第i+1位的怪物,那么第1座城市可能会有结余,而后面的英雄因为自己的城市的怪物已经被杀掉一部分了,所以可能不能杀满B[i]个,所以之前的做法应该是最优的。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    int n;
    int a[100005];
    int b[100005];
    long long ans;
    
    int main(){
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        cin>>n;
        for(int i=1;i<=n+1;i++){
            cin>>a[i];
        }
        for(int i=1;i<=n;i++){
            cin>>b[i];
        }
        for(int i=1;i<=n;i++){//贪心的,让英雄先杀自己城市的怪物,再杀下一个城市的
            if(b[i]<=a[i]){
                ans+=b[i];
            }else{
                b[i]-=a[i];
                ans+=a[i];
                ans+=min(a[i+1],b[i]);
                a[i+1]-=min(a[i+1],b[i]);
            }
        }
        cout<<ans<<endl;
    
        return 0;
    }
    

    D - Digits Parade

    题目大意:

    给你一个字符串S,包含0~9?。在?中填入0~9,使得得到的数对13取模余5

    可以有前导零

    题目做法:

    DP。由于数据范围很大,有10^5那么大,但是13这个数字很小,是一个突破口。于是:

    我们建立一个二维数组DPDP[i][j]表示计算到第i位(第i位还没有填入,此时i0开始计算)时有多少种13取模余j的方法。正向思考,DP[i+1][(j*10+<填入的数字>)%13]+=DP[i][j],如果这一位是?,那么填入的数字从19都要计算一遍。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    const int mod=1000000007;
    
    string s;
    int n;
    int dp[100005][15];
    
    int main(){
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        cin>>s;
        int n=s.size();
        dp[0][0]=1;
        for(int i=0;i<n;i++){
            if(s[i]=='?'){
                for(int j=0;j<13;j++){
                    for(int k=0;k<10;k++){//尝试填入0~9
                        dp[i+1][(j*10+k)%13]+=dp[i][j];
                        if(dp[i+1][(j*10+k)%13]>=mod)dp[i+1][(j*10+k)%13]-=mod;//常数优化
                    }
                }
            }else{
                for(int j=0;j<13;j++){
                    dp[i+1][(j*10+s[i]-'0')%13]+=dp[i][j];
                    if(dp[i+1][(j*10+s[i]-'0')%13]>=mod)dp[i+1][(j*10+s[i]-'0')%13]-=mod;//常数优化
                }
            }
        }
        cout<<dp[n][5]<<endl;
    
        return 0;
    }
    

    其实这个常数优化并没有什么用,因为计算下标时还是需要取模。

    E - Golf

    我不会,所以就没有办法写了。

    放张官方题解:

    题解图片

    官方题解链接

    F - Strings of Eternity

    题目大意:

    给你两个字符串st,问你是否有一个非负整数i满足下列条件并且i是有限的,如果是,那么求出i的最大值。

    条件:有一个非负整数jit连接起来是js连接起来的字串。

    说人话(其实也是我比较喜欢的方式)就是给你两个串st,然后无限多个s连接起来,是否可以找到有限个t连接起来是s的子串。如果无限多个t都是字串,那么就输出-1

    题目做法:

    想法来自我的同学。首先,你把足够多的s连接起来,然后每一个位置i都查看si开始的后缀子串并记为s2,查看t是否是s2的前缀。新开一个数组suf记录是或否。然后,从后往前,做一个类似前缀和的操作,如果第i位是1,那么就加上第i+|t|位的值(|t|t的长度),可以在O(n)时间内求出最长的连续的t作为连续的s的子串时,这个t的连续的个数。

    这个匹配操作,我们可以使用Hash来把复杂度控制在O(n)里(其实KMPZ算法也可以实现)。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const int mod=1145411919;
    const int p=810;
    //这么臭的哈希值应该没人会卡吧
    string s,t;
    int ans;
    ll pw[16000005];
    ll h[16000005];
    ll ht[16000005];
    int suf[16000005];
    
    inline ll gh(int x){//求s中第x位开始的长|t|字符串的哈希值
        if(x+t.size()>s.size())return -1;
        return (h[x+t.size()-1]-h[x-1]*pw[t.size()]%mod+mod)%mod;
    }
    
    int main(){
    
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout.tie(0);
    
        cin>>s>>t;
        while(s.size()<t.size()*2)s=s+s;
        s=s+s;
        s=s+s;
        s=s+s;//构建出足够长的s
        pw[0]=1;
        for(int i=1;i<=16000000;i++){
            pw[i]=pw[i-1]*p%mod;
        }//预先求k的i次方,存入pw[i]
        h[0]=s[0]-'a'+1;
        for(int i=1;i<s.size();i++){
            h[i]=(h[i-1]*p+s[i]-'a'+1)%mod;
        }//h[i]代表s到i的hash值
        ht[0]=t[0]-'a'+1;
        for(int i=1;i<t.size();i++){
            ht[i]=(ht[i-1]*p+t[i]-'a'+1)%mod;
        }//ht[i]代表t到i的hash值
        for(int i=0;i<s.size();i++){
            suf[i]=ht[t.size()-1]==gh(i);
        }//suf功用同上
        for(int i=s.size()-t.size();i>=0;i--){
            if(suf[i])suf[i]+=suf[i+t.size()];
            ans=max(ans,suf[i]);
        }//和做法中解释的一样
        if(ans+1>=s.size()/t.size()){
            cout<<-1<<endl;
            return 0;
        }//判断t的连接是否过多,近似无限
        cout<<ans<<endl;
    
        return 0;
    }
    

    结束语

    感谢你看完,如果你想支持我,你可以登录账号,把对我的建议和意见写在下面,帮助我取得进步。

  • 相关阅读:
    测开之路一百一十:bootstrap图片
    测开之路一百零九:bootstrap列表
    测开之路一百零八:bootstrap表格
    测开之路一百零七:bootstrap排版
    测开之路一百零六:bootstrap布局
    学生管理之原生分页方法
    Ajax文件上传三式
    学生管理之模板继承
    Django之Models的class Meta
    [C++]指针/指针数组/数组指针/多维指针/单值指针/多值指针
  • 原文地址:https://www.cnblogs.com/BlahDuckling747/p/12019558.html
Copyright © 2011-2022 走看看