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 。
记 表示经过 i i 的 LDS 个数, 为总的 LDS 个数。考虑不合法的 LIS 长什么样,记它为 i1,i2,⋯,ik i 1 , i 2 , ⋯ , i k ,那么所有 LDS 一定与它有交集,又因为交集不超过 1