细节/数学/滑动窗口

发布于:2025-06-24 ⋅ 阅读:(13) ⋅ 点赞:(0)

 题目意思:

判断字符串是否可以按照题目条件缩短。

思路:

用栈的思想写,对每一次的大小写都进行滚动判断。

tips:

这里面要注意的东西就有一点多了,首先是字符串的遍历问题auto更方便,其次是对小写和大写字母的判断,可以说字符串大部分的细节这道题目都有涉及。

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int n;cin>>n;
    string ac;cin>>ac;
    stack<char>p;
    for(auto it:ac){
        if(!p.empty()){
            //这里是判断是否为空,但是容易写成while
            char top=p.top();
            //找出顶端的字母
            if(it>top&&islower(top)&& islower(it)&&(it-'a'+1+top-'a'+1==27)){
                //小写的情况下,两者都要是小写的,而且满足一定的条件,后大于前且两者相加为27
                p.pop();
                continue;
            }
            if(it<top&&isupper(top)&&isupper(it)&&(it-'A'+1+top-'A'+1==27)){
                //大写的情况下,两者都要是大写的,而且满足一定的条件,前大于后且两者相加为27
                p.pop();
                continue;
            }
        }
        p.push(it);
    }
    cout<<p.size()<<endl;
}
signed main(){
    int n=1;
    while(n--){
        solve();
    }
}

题目意思:

给定一些数字,判断这些数字是否能用其他平方数字通过迭代的方式得到。

思路:

平方数字有4,9,16,25....但是我们这里只需要取4,9即可,因为大于9的平方数字我们都可以通过较小的平方数字得到。故有意义的平方数字只有4,9。

拿4举例子

1,4,7,...3k+1

拿9举例子

1,9,17,...8k+1

拿25举例子

1,24,47,...23k+1

之后由于题目中可以反复取相同或者不相同的平方数字进行若干次操作,我们可以对上述数字进行通解写法,3a+1+23b+8c+...(其他平方数字),但是我们要找到这一串通解表达最小的数字是多少。

麦乐鸡定理  

我们可以根据上数定理找到最小可表达的数字,这里我们用3a+8b+1得到14。

故大于14的数字该表达式都可以表达。

我们只需要在14内部进行特判即可。(手动模拟一下)

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
    int x;cin>>x;
    if(x==2||x==3||x==5||x==6||x==8||x==11||x==14){
        cout<<"No"<<endl;
    }
    else{
        cout<<"Yes"<<endl;
    }
}
signed main(){
    int n=1;cin>>n;
    while(n--){
        solve();
    }
}

题目意思:

给定一个数组和若干次给每个数字加一的操作下,找到长度为m的字串且奇偶交替的最小次数。

思路:滑动窗口想法,对于每一个长度为m的字串进行判断找最小,从头到尾遍历一遍。

奇偶交替的情况可以是奇偶奇偶奇偶也可以是偶奇偶奇偶奇,说到底是数组下标和数字之间的关系。故我们可以将奇数标记为1,偶数标记为0,进行状压转移。

最后按照两种情况分别求个前缀和(如果数字的奇偶性和当下交替情况不符合,我们就直接操作加1)

#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
    int n, m;
    cin >> n >> m;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];  // 输入数组a
    }
    // 定义两个数组aa和bb,分别表示将a[i]调整为以奇数开头和偶数开头的奇偶交替序列所需的操作次数
    vector<int> aa(n), bb(n);
    for (int i = 0; i < n; i++) {
        // aa[i]: 如果a[i]的奇偶性与i的奇偶性不一致,则需要调整(操作次数为1),否则为0
        aa[i] = (a[i] % 2 != i % 2) ? 1 : 0;
        // bb[i]: 如果a[i]的奇偶性与i的奇偶性相反(即i是偶数时a[i]是奇数,i是奇数时a[i]是偶数),则需要调整(操作次数为1),否则为0
        bb[i] = (a[i] % 2 != !(i % 2)) ? 1 : 0;
    }
    // 前缀和数组,用于快速计算区间和
    vector<int> qian(n + 1, 0), hou(n + 1, 0);
    for (int i = 0; i < n; i++) {
        qian[i + 1] = qian[i] + aa[i];  // qian[i+1]表示前i个元素中aa的和
        hou[i + 1] = hou[i] + bb[i];    // hou[i+1]表示前i个元素中bb的和
    }
    int answer = 8e18;  // 初始化为一个很大的数,表示无穷大
    // 滑动窗口,遍历所有长度为m的子数组
    for (int i = 0; i + m <= n; i++) {
        // 计算当前窗口内aa的和(即调整为以奇数开头的奇偶交替序列的操作次数)
        int sum = qian[i + m] - qian[i];
        // 计算当前窗口内bb的和(即调整为以偶数开头的奇偶交替序列的操作次数)
        int cnt = hou[i + m] - hou[i];
        // 更新最小操作次数
        answer = min({answer, sum, cnt});
    }
    cout << answer << endl;
}

signed main() {
    int t = 1;
    while (t--) {
        solve();
    }
    return 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到