蓝桥杯2023真题(2)

1.硬币兑换

蓝桥杯2023真题(2)_第1张图片

#include 
using namespace std;
int main()
{
  int a[5000] = {0}, ans = 0;
  //coin1
  for(int i = 1; i <= 2023; i++){
    //coin2
    for(int j = i + 1; j <= 2023; j++){
      a[i + j] += i;
      ans = max(ans, a[i + j]);
    }
  }
  cout<<ans;
  return 0;
}

2.更小的数

蓝桥杯2023真题(2)_第2张图片

//暴力枚举
#include 
#include 
using namespace std;
int main()
{
  string s;
  cin>>s;
  int n = s.size(), ans = 0;
  for(int i = 0; i < n; i++){
    for(int j = i + 1; j < n; j++){
      string t = s;
      //反转[i, j + 1)的字符
      reverse(t.begin() + i, t.begin() + j + 1);
      if(t < s) ans++;
    }
  }
  cout<<ans;
  return 0;
}

//区间dp
#include 
using namespace std;
const int N = 5005;
int f[N][N], a[N]; //f[i][j]: [i, j]是否可以反转

int main()
{
  string s;
  cin>>s;
  int n = s.size(), ans = 0;
  //字符转化成数字
  for(int i = 1; i <= n; i++) a[i] = s[i - 1] - '0';
  //区间长度
  for(int len = 1; len < n; len++){
    //区间两个端点
    for(int i = 1, j = i + len; j <= n; i++, j = i + len){
      if(a[i] == a[j]){
        //长度小于等于3,首位相同,反转了值一样
        if(j - i == 1 || j - i == 2) f[i][j] = 0;
        //如果长度大于3,那就往里面扩展,判断是否满足
        else f[i][j] = f[i + 1][j - 1];
      }
      if(a[i] > a[j]) f[i][j] = 1;
      if(a[i] < a[j]) f[i][j] = 0;
      if(f[i][j]) ans++;
    }
  }
  cout<<ans;
  return 0;
}

3.颜色平衡树

蓝桥杯2023真题(2)_第3张图片

#include
#include
#include
using namespace std;
const int N = 2e5 + 10;
int h[N], e[N], ne[N], idx;
int n, c[N], ans;
unordered_map<int, int> mp; //根节点存储所有的颜色和数量

void add(int x, int y){
  e[idx] = y;
  ne[idx] = h[x];
  h[x] = idx;
  idx++;
}

//m存储的是父节点,必须加引用
void dfs(int u, unordered_map<int, int> &m){
  //如果是叶子节点,就返回
  if(h[u] == -1){
    //cout<
    m[c[u]]++;
    ans++;
    return;
  }
  //存储当前节点加他的子节点的颜色和数量
  unordered_map<int, int> t;
  t[c[u]]++;
  //遍历当前节点的子节点
  for(int i = h[u]; i != -1; i = ne[i]){
    int j = e[i];
    //cout<
    dfs(j, t);
  }
  
  int pre = 0, f = 1;
  //遍历父节点加子节点
  for(auto it : t){
    //父节点加上当前节点和当前节点的子节点
    m[it.first] += it.second;
    //如果有颜色,且当前节点和他的子节点中有颜色数量不同的
    if(pre && pre != it.second) f = 0;
    pre = it.second; 
  }
  if(f){
    //cout<
    ans++;
  }
}

int main(){
  memset(h, -1, sizeof(h));
  scanf("%d", &n);
  int x, y;
  for(int i = 1; i <= n; i++){
    scanf("%d%d", &x, &y);
    add(y, i);
    c[i] = x;
  }
  //传入根节点
  dfs(1, mp);
  printf("%d", ans);
  return 0;
}

4.买瓜

蓝桥杯2023真题(2)_第4张图片

#include
#include
using namespace std;
double a[35], b[35];
int n, m, ans = 1e9, f;

bool cmp(const double &p, const double &q){
  return p > q;
}

//第几个瓜,切了几刀,总和多少
void dfs(int u, int cnt, double sum){
  //如果当前总和大了,或者小了,就减枝
  if(sum > m || sum + b[u] < m) return;
  if(sum == m){
    f = 1;
    ans = min(ans, cnt);
    return;
  }
  //这个判断要放在后面,防止最后一个数没算上就返回了
  if(u > n) return;
  dfs(u + 1, cnt, sum + a[u]);
  dfs(u + 1, cnt + 1, sum + a[u] / 2);
  dfs(u + 1, cnt, sum);
}

int main()
{
  cin>>n>>m;
  for(int i = 1; i <= n; i++) cin>>a[i];
  //降序排列,先加重量大的
  sort(a + 1, a + n + 1, cmp);
  //存储后缀和,用来减枝
  for(int i = n; i > 0; i--) b[i] = b[i + 1] + a[i];
  dfs(1, 0, 0);
  if(!f) printf("-1");
  else printf("%d", ans);
  return 0;
}

5.网络稳定性

蓝桥杯2023真题(2)_第5张图片

give up

6.异或和之和

蓝桥杯2023真题(2)_第6张图片

//暴力枚举
#include 
using namespace std;
const int N = 1e5 + 10;
int a[N], n;
long long ans;

int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; i++)
        scanf("%d", &a[i]);
    for(int i = 0; i < n; i++){
        int res = 0;
        for(int j = i; j < n; j++){
            res ^= a[j];
            ans += res;
        }
    }
    printf("%lld", ans);
    return 0;
}

//位运算
//a ^ b = c -> b ^ c = a, a ^ c = b
//[l, r]的异或和 = pre[r] ^ pre[l - 1], pre是前缀异或和
#include 
using namespace std;
const int N = 1e5 + 10;
int a[N], cnt[25][5], n; //cnt[i][j]: 第i位j的个数
long long ans;

int main()
{
  scanf("%d", &n);
  for(int i = 1; i <= n; i++){
    scanf("%d", &a[i]);
    //异或前缀和
    a[i] ^= a[i - 1];
  }

  //[i, j]的异或和 = a[j] ^ a[i - 1],因为 a ^ b = c,a ^ c = b
  // for(int i = 1; i <= n; i++)
  //   for(int j = i; j <= n; j++)
  //     ans += a[j] ^ a[i - 1];
  //下面就是优化这个步骤

  //遍历二进位每一位
  for(int i = 0; i <= 20; i++)
    //遍历每一个数,j从0开始是因为计算前缀异或和要用到a[0]
    for(int j = 0; j <= n; j++)
      cnt[i][(a[j] >> i) & 1]++;
  //乘法原理,把所有情况乘起来
  for(int i = 0; i <= 20; i++){
    ans += (long long)cnt[i][0] * cnt[i][1] * (1 << i);
  }
  printf("%lld", ans);
}

你可能感兴趣的:(备战蓝桥杯,蓝桥杯,职场和发展)