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

結束語

感謝你看完,若是你想支持我,你能夠登陸帳號,把對個人建議和意見寫在下面,幫助我取得進步。

相關文章
相關標籤/搜索