1 条题解
-
0
解题思路
- 初始化与预处理:读取糖果类型数量
n
、每种糖果的重量w[i]
、查询数量m
和每个查询的人数P[j]
。计算所有糖果重量的最小公倍数W
,以此作为状态表示的周期,初始化用于记录不同重量组合数量的数组f
。 - 动态规划计算组合数:利用动态规划的方法,根据糖果的重量和数量限制,计算在总重量为
n*W
范围内,每种重量对应的糖果盒组合数量,填充数组f
。 - 二分查找确定最小重量:对于每个查询的人数
P[j]
,在一定重量范围内(最大为100 * P[j]
)进行二分查找。通过check
函数检查当前重量k
下,能否得到至少P[j]
种不同的糖果盒组合。如果可以,则更新最小重量结果;如果遍历完所有可能重量都无法满足,则输出“no candy for you”。
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> using namespace std; int n, w[10], W; long long f[200000]; int gcd(int a, int b) { while (b) { int t = a % b; a = b; b = t; } return a; } bool check(long long k, int r, long long p) { long long tp; int i, j; for (i = 0; i < n; i++) { if (k < i) break; if (f[i * W + r] == 0) continue; tp = p / f[i * W + r]; for (j = 1; j <= n - 1; j++) tp *= j; for (j = 1; j < n; j++) tp /= j + k - i; if (tp == 0) return true; tp = f[i * W + r]; for (j = 1; j < n; j++) tp *= j + k - i; for (j = 1; j <= n - 1; j++) tp /= j; p -= tp; } return p == 0; } int main() { int m, i, j, k, t, u = 0, r; long long lt, rt, mt; long long sum, p, res; while (scanf("%d", &n), n) { u++; W = 1; for (i = 1; i <= n; i++) { scanf("%d", &w[i]); W = (W / gcd(W, w[i])) * w[i]; // Safer calculation to prevent overflow } for (i = 0; i < n * W; i++) f[i] = 0; f[0] = 1; for (i = 1; i <= n; i++) { if (w[i] == W) continue; for (r = 0; r < w[i]; r++) { k = n * W - w[i] + r; sum = 0; for (j = w[i]; j < W; j += w[i]) sum += f[k - j]; f[k] += sum; for (k -= w[i]; k >= 0; k -= w[i]) { sum -= f[k]; if ((t = k + w[i] - W) >= 0) sum += f[t]; f[k] += sum; } } } printf("Set %d\n", u); scanf("%d", &m); while (m--) { scanf("%lld", &p); // Correct format specifier for long long res = p * 100 + 1; for (r = 0; r < W; r++) { lt = -1; if (r == 0) lt++; rt = (res - r) / W + 1; while (lt + 1 < rt) { mt = (lt + rt) >> 1; if (check(mt, r, p)) rt = mt; else lt = mt; } if (res > rt * W + r) res = rt * W + r; } if (res > 100 * p) puts("no candy for you"); else printf("%lld\n", res); // Correct format specifier for long long } } return 0; }
- 初始化与预处理:读取糖果类型数量
- 1
信息
- ID
- 1764
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 16
- 已通过
- 1
- 上传者