Codeforces Round #256 (Div. 2)

本文提供四道算法竞赛题目的解析及代码实现,包括木板涂色最优化问题、矩阵元素查找、递归因子序列等,采用C++实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A, B题不多说

C题:

题意:给你n个相邻的木板, 每个木板宽度为1, 高度为ai,给你一把刷子, 每一次能刷宽度为1的连续的木板, 问最少刷几次能使全部木板换一种颜色

 分析:答案最大为n, 就是每次都竖着刷, 若存在先横着刷的情况 则一定是把n个木板中最小的高度全部刷掉, 这样相当于每个木板的高度减去最小高度后需要的次数, 加上最小木板的高度, 递归求解

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int n, a[5010];

int dfs(int l, int r) {
   int res = 0;
   int min_v = 1 << 30;
   for(int i=l; i<=r; i++) min_v = min(min_v, a[i]);
   for(int i=l; i<=r; i++) a[i] -= min_v;
   res += min_v;
   for(int i=l; i<=r; i++) if(a[i]) {
     for(int j=i; j<=r; j++) {
        if(a[j] == 0) {
           res += dfs(i, j-1);
           i = j;
           break;
        }
        else if(a[j] && j == r) {
            res += dfs(i, j);
            i = j;
            break;
        }
     }
   }
   return min(res, r-l+1);
}
int main() {
  scanf("%d", &n);
  for(int i=1; i<=n; i++) scanf("%d", &a[i]);
  printf("%d\n", dfs(1, n));
  return 0;
}

D题:

题意:给你一个n*m的矩阵, i, j位子的大小为i*j, 求第k小的数

分析:二分求解,一开始最小值为1, 最大值为n*m,二分球的mid = (n + m) >> 1, 求小于等于Mid的数 

for(int i=1; i<=n; i++) res += min(m, mid / n), 不过感觉还是有问题, 难道不会最后二分球的一个不存在的值满足条件吗, 虽然一直没有找到反例

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;

int n, m;
ll k;

ll f(ll x) {
  ll res = 0;
  for(int i=1; i<=n; i++)
    res += min((ll)m, x / i);
  return res;
}
int main() {
  cin >> n >> m >> k;
  ll l = 1, r = (ll)n * m;
  ll ans = -1;
  while(l <= r) {
    ll mid = (l + r) >> 1;
    if(f(mid) >= k) {
        ans = mid;
        r = mid - 1;
    }
    else
        l = mid + 1;
  }
  printf("%I64d\n", ans);
  return 0;
}


E题:

题意:给你x, k, f()是每一数的因子的递增排列, xi = f(x i -1), 求x(k);

分析:dfs递归求解, 搜索的过程就像一颗搜索树

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;

ll a[1000010], x, k;
ll sum, tot;
vector <ll> div1[111111];

void dfs(ll cnt, ll cur) {
  if(sum >= 100000)  return;
  if(cnt == 1) {
    printf("1 ");
    sum++;
    return;
  }
  if(cur == 0) {
    printf("%I64d ", a[cnt]);
    sum++;
    return;
  }
  for(ll i=0; i<div1[cnt].size(); i++) {
     dfs(div1[cnt][i], cur - 1);
     if(sum >= 100000)  return;
  }
}
int main() {
  cin >> x >> k;
  sum = 0;
  tot = 0;
  for(ll i=1; i*i <= x; i++) if(x % i == 0) {
    a[++tot] = i;
    if(i*i != x) a[++tot] = x / i;
  }
  sort(a+1, a+tot+1);
  for(ll i=1; i<=tot; i++)
    for(ll j=1; j<=i; j++) if(a[i] % a[j] == 0)
      div1[i].push_back(j);
  dfs(tot, k);
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值