ABC135记录

date: 2019-07-28ios

A - Harmony

题目大意:

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

题目作法:

聪明的读者读到这里确定已经发现了,这其实就是平均数,可是,要特判AB的差是奇数的状况:此时K不是整数,因此输出"IMPOSSIBLE"git

代码:

#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]个。spa

题目作法:

贪心显然地,因为第i位英雄只能影响第ii+1城市,因此i以前的城市这位英雄都不能影响,因此尽可能让第i位英雄战胜第i座城市里的怪物,打不完B[i]个在去下一座城市。code

若是第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取模余5ci

能够有前导零

题目作法:

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;
}

结束语

感谢你看完,若是你想支持我,你能够登陆帐号,把对个人建议和意见写在下面,帮助我取得进步。

相关文章
相关标签/搜索