【牛客周赛】round14赛后总结

发布时间 2023-10-12 17:03:25作者: 木易meow

碎碎念

赛时没出题(真可恶吖)在上晚自习,补了一下。ACD都套着字符串的外壳,差点直接劝退,后来仔细一读发现和字符串没什么关系...大概字符串的用处是为了劝退我这种有些怂字符串的人叭。

A. 小红的环形字符串

  • 题意:对于给定的环形字符串s,可以删除相邻的两个相同字母,问最多删除多少个字符
  • 思路:相邻删除和头尾删除,注意删之后的相邻如何判断——deque
  • code:
#include<iostream>
#include<queue>
using namespace std;
const int MAXN=1e5+10;
char s[MAXN];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s[i];
    }
    int l=1,r=n,cnt=0;
    while(s[l]==s[r]){
        if(l>=r)break;
        cnt+=2;
        l++;
        r--;
    }
    deque<char>q;
    for(int i=l;i<=r;i++){
        if(q.size() && q.back()==s[i]){
            q.pop_back();
            cnt+=2;
        }
        else if(q.front()==s[r]){
            r--;
            q.pop_front();
            cnt+=2;
        }
        else{
            q.push_back(s[i]);
        }
    }
    cout<<cnt<<endl;
    return 0;
}

B.小红的乘除变换

  • 题意:通过多次将 x 乘以5,或当x 是6的倍数,将 x 除以6 的操作,使x转变为y。问最小操作次数
  • 思路:最小操作次数=(y比x多的⑤的因数个数)+(x比y多的6的因数个数)。当含有其他因子时或这两项存在负数时为-1
  • code
#include<iostream>
#define int long long
using namespace std;
void sol(){
    int x,y,ans=0;
    cin>>x>>y;
    int x5=0,y5=0;
    while(x%5==0){
        x5++;
        x/=5;
    }
    while(y%5==0){
        y5++;
        y/=5;
    }
    if(x5>y5){
        cout<<"-1"<<endl;
        return;
    }
    ans=y5-x5;
    int x6=0,y6=0;
    while(x%6==0){
        x6++;
        x/=6;
    }
    while(y%6==0){
        y6++;
        y/=6;
    }
    if(x6<y6){
        cout<<"-1"<<endl;
        return;
    }
    ans+=x6-y6;
    if(x!=y){
        cout<<"-1"<<endl;
    }
    else{
        cout<<ans<<endl;
    }
    return;
    
}
signed main(){
    int t;
    cin>>t;
    while(t--){
        sol();
    }
    return 0;
}

C.小红的子串

  • 题意:小红拿到了一个长度为n的字符串,她准备选取一段子串,满足该子串中字母的种类数量在[l,r]之间。小红想知道,一共有多少种选取方案?
  • 思路:双指针
  • code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
 
const int N = 1e6 + 10;
int n, l, r, num;
char S[2 * N];
 
int solve(int m){
    int b[26], res = 0, num = 0;
    memset(b, 0, sizeof b);
    for(int i = 0, j = 0 ; i < n ; i ++){
        b[S[i] - 'a'] ++;
        if(b[S[i] - 'a'] == 1)  ++ num;
        while(num > m){
            b[S[j] - 'a'] --;
            if(b[S[j] - 'a'] == 0)  num --;
            ++ j;
        }
        res += i - j + 1;
    }
 
    return res;
}
signed main(){
    scanf("%d%d%d%s", &n, &l, &r, S);
    printf("%lld\n", solve(r) - solve(l - 1));
 
    return 0;
}

D.回文权值和(总算没小红了)

  • 题意:定义一个字符串的权值为:长度为3的回文子串的数量。
    求长度为n的、仅由小写字母组成的所有字符串的权值之和。答案对10^9+7取模。
  • 思路:第一和第三位相同,其余位置任选,所以26^(n-1)种,这两个相同的位置的话有n-2种可能。
    所以总共为(n-2) * qpow(26,n-1)