<蓝桥杯备考刷题>蓝桥杯15届省赛冲刺营结营考试:七彩之城的独特序列+完美队列的数目(关于子序列的理解)

今天做了一遍 蓝桥杯15届省赛冲刺营结营考试 遇到的问题还不小

对于子序列的问题不透彻(只知道dp中最长递增子序列)

其实做完这些题后 我明白了子序列和子数组的差别和相同的点

那么遇到子序列问题 一般不会让你排序 因为最后要求的答案一般都是有序的

包括子数组问题 所以我想告诉大家我对于这类题目的理解:

第六题:

七彩之城的独特序列

对于这样的一个题目 我的第一想法就是排列组合 最后我发现排列组合会打乱原本因该有的次序,并且排列组合的时间复杂度是非常高的:大概是O(n!)这么大所以我没有想着怎么去写了 并且第一次写的时候我居然以子数组的形式去写!大家记得审题子数组和子序列问题!!!!


第一次代码:

#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 1e5+10;
int arr[N];
int ans=  0;
int main()
{
  cin>>n;
  for(int i =1;i<=n;i++){
    cin>>arr[i];
  }
  for(int len = 1;len<=n;len++){
    for(int i = 1;i+len-1<=n;i++){
      int j = i+len-1;
      unordered_set<int> s;
      for(int k = i;k<=j;k++){
        s.insert(arr[i]);
      }
      if(s.size()==len) ans++;
    }
  }
  cout<<ans;
  // 请在此输入您的代码
  return 0;
}

很明显时间复杂度为O(n^3)直接爆了 但是我就只想骗骗分0.0

后面发现完全错误直接归为0分 就是用了子数组的思想


然后最后我认识到了子序列的问题 -》它实际上是一个开关的问题

什么是开关呢?

假设这是我们的数组,如果要取一个没有相同元素的子序列 那么每个元素我们都可以选可以不选并且位置不会发生改变(该在你前面的总会在你前面)这就符合我们的开关

这就是开关的问题!那么我们的1元素可以选可以不选 2元素可以选第一个 可以选第二个 可以选第三个 可以不选 这四种情况 那么每个元素的情况实际上就是存在的元素的个数+1

那么最后的答案即是:所有元素的可选择数量相乘(特判:不能一个都不选)


#include <bits/stdc++.h>
using namespace std;
int n;
const int N = 1e5+10,MOD = 1e9+7;
long long arr[N];
long long ans=  1;
int main()
{
  cin>>n;
  
  unordered_map<int,int> mp;
  for(int i =1;i<=n;i++){
    cin>>arr[i];
    mp[arr[i]]++;
  }
  for(auto s:mp){
    ans*=s.second+1;
    ans%=MOD;
  }
  cout<<(ans-1)%MOD;
  // 请在此输入您的代码
  return 0;
}

这就是我们的正解

那么来看第二个题目:完美队列的数目

这个题目是整套卷子的第八题(都是关于子序列问题0.0)

这个题目针对于选法 那么我们可以先把所有元素排序 并且每次都给定一个区间,去判断区间这个区间是否合法(合法是指最弱的和最强的和<=k)

那么其实这个问题也是一个开关问题 

我们看这个题目的开关实际上是每个区间中的开关 那么每个人可以选可以不选 则每个人有2种选法,最终一个合法区间的答案就是 2^(l-r)

我们直接上代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10,MOD = 1e9+7;
typedef long long LL;
LL arr[N];
int n, k;
LL ans;
LL qmi(int a,int b,int c){
  LL ans= 1;
  while(b){
    if(b&1) ans = (LL) ans*a%c;
    b>>=1;
    a = (LL) a*a%c;
  }
  return ans;
}
int main()
{
    // 请在此输入您的代码
    cin >> n >> k;
    for (int i = 1; i <= n; i++){
      cin >> arr[i];
      if(arr[i]*2<=k) ans++;
    }
    sort(arr + 1, arr + n + 1);
    int l = 1,r = n;
    while(l<=r){
      if(arr[l]+arr[r]>k){
        r--;
      }else{
        ans = (ans+qmi(2,r-l,MOD)-1)%MOD;
        l++;
      }
    }
    cout << ans;
    return 0;
}

因为常规的pow函数时间复杂度为N 那么总时间复杂度为N^2一定会超时 这里可以用到快速幂(qmi)模板来解决

并且区间不需要全部去枚举 只需要用一个滑动窗口的方法(双指针)可以使得复杂度为N

总体时间复杂度为NlogN 完美解决数据为1e5的问题

最后:

又ac一道!


  • 13
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
蓝桥杯是一个著名的计算机竞赛,对于备考蓝桥杯Python组国二,以下是一些建议和备考策略: 1. 熟悉考试内容:了解蓝桥杯Python组国二的考试内容和题型,包括编程题、选择题等。可以通过查看往年的试题和题解来熟悉考试的难度和要求。 2. 学习基础知识:蓝桥杯考察的是Python语言的基础知识和编程能力,因此需要掌握Python的语法、数据类型、函数、模块等基础知识,并能够熟练运用。 3. 刷题练习:通过刷题来提高编程能力和解题技巧。可以选择一些蓝桥杯的往年试题进行练习,理解题目的要求,思考解题思路,并进行编程实现。 4. 学习算法和数据结构:蓝桥杯的编程题通常涉及到算法和数据结构的应用,因此需要学习一些常用的算法和数据结构,如排序算法、查找算法、栈、队列等。 5. 多做模拟考试:在备考过程中,可以进行一些模拟考试,模拟真实考试的环境和时间限制,提高解题速度和应对考试压力的能力。 6. 学习优秀的解题思路:可以参考一些优秀的解题思路和代码,学习别人的思考方式和编程技巧,提高自己的解题能力。 7. 多交流和讨论:可以参加一些蓝桥杯的学习交流群或论坛,与其他备考者进行交流和讨论,分享经验和解题思路。 8. 坚持练习和复习:备考蓝桥杯需要持续的学习和练习,每天保持一定的学习时间,不断巩固和提高自己的编程能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值