CodeForces Gym 101821 简要题解

Smart Vending

注意到策略其实是没有用的,所以需要想一种办法加速模拟。

注意到纸币价格只有 106 10 6 ,首先用硬币能买就买,之后的操作中,尽量多用纸币,这样可以将硬币数量控制在 106 10 6 以内,不断模拟下去一定会形成环,加上记忆化就可以了。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
  char c = getchar();
  bool f = false;
  for (x = 0; !isdigit(c); c = getchar()) {
    if (c == '-') {
      f = true;
    }
  }
  for (; isdigit(c); c = getchar()) {
    x = x * 10 + c - '0';
  }
  if (f) {
    x = -x;
  }
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
  return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
  return a > b ? a = b, true : false;
}

const int N = 1000005;
const int base = 1000000;

int b, c, r, tot, mem_b[N];
LL ans, mem_ans[N];
bool mem[N];

int main() {
#ifdef wxh010910
  freopen("d.in", "r", stdin);
#endif
  Read(b), Read(c), Read(r), Read(tot), tot += c;
  ans += c / r, c %= r;
  int c_small = c % base, c_large = c / base, r_small = r % base, r_large = r / base, b_need = r_large - c_large;
  if (c_small < r_small) {
    if (b >= b_need + 1 && tot - c_small >= base - r_small) {
      b -= b_need + 1, ++ans, c = c_small - r_small + base;
    } else {
      printf("%lld\n", ans);
      return 0;
    }
  } else {
    if (b >= b_need) {
      b -= b_need, ++ans, c = c_small - r_small;
    } else {
      printf("%lld\n", ans);
      return 0;
    }
  }
  while (true) {
    if (mem[c]) {
      break;
    }
    mem[c] = true, mem_b[c] = b, mem_ans[c] = ans;
    if (c < r_small) {
      if (b >= r_large + 1 && tot - c >= base - r_small) {
        b -= r_large + 1, ++ans, c += base - r_small;
      } else {
        printf("%lld\n", ans);
        return 0;
      }
    } else {
      if (b >= r_large) {
        b -= r_large, ++ans, c -= r_small;
      } else {
        printf("%lld\n", ans);
        return 0;
      }
    }
  }
  LL t = b / (mem_b[c] - b);
  ans += t * (ans - mem_ans[c]), b %= mem_b[c] - b;
  while (true) {
    if (c < r_small) {
      if (b >= r_large + 1 && tot - c >= base - r_small) {
        b -= r_large + 1, ++ans, c += base - r_small;
      } else {
        printf("%lld\n", ans);
        return 0;
      }
    } else {
      if (b >= r_large) {
        b -= r_large, ++ans, c -= r_small;
      } else {
        printf("%lld\n", ans);
        return 0;
      }
    }
  }
#ifdef wxh010910
  Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
  return 0;
}

LIS vs. LDS

一个性质是 LIS 和 LDS 交集的大小至多为 1 1

f i 表示经过 i i 的 LDS 个数, a l l 为总的 LDS 个数。考虑不合法的 LIS 长什么样,记它为 i1,i2,,ik i 1 , i 2 , ⋯ , i k ,那么所有 LDS 一定与它有交集,又因为交集不超过 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值