T1
二分物品的最大价值,根据这个可以计算出物品数量
最后判断剩下的钱是否可以多买一个
T3
n<=12时可以dp,\(f_{i,j,k}\)表示第 i 位最高位值为 j ,总和为k的方案数,\(g_{i,j}\)表示前 i 位总和为 j 的方案数
然后可以按位确定
n>12时,共有\(\frac{n^3}{9}\)位,从这些之中选两个超过了\(n^4\)
然后考虑先减去选一位的方案数 ,然后枚举选两位
代码
T1
#include <bits/stdc++.h>
using namespace std;
#define int __int128
int a, b, c, d, x;
inline int js(int y) { return (y - 1) * y / 2; }
inline int jsa(int x) { return a * x + js(x) * b; }
inline int jsc(int x) { return c * x + js(x) * d; }
inline int min_(int x, int y) { return x > y ? y : x; }
inline int max_(int x, int y) { return x > y ? x : y; }
inline int read() {
int s = 0;
char ch = getchar();
while (ch > '9' || ch < '0') ch = getchar();
while (ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s;
}
int check(int s) {
if (s < a && s < c)
return 0;
int num1 = (s - a) / b + 1;
if (s < c)
return jsa(num1) <= x ? num1 : -1;
int num2 = (s - c) / d + 1;
if (s < a)
return jsc(num2) <= x ? num2 : -1;
if (jsa(num1) + jsc(num2) <= x)
return num1 + num2;
return -1;
}
void write(int x) {
if (!x) {
putchar('0');
return;
}
if (x / 10)
write(x / 10);
putchar(x % 10 + '0');
return;
}
signed main() {
FILE* p = freopen("money.in", "r", stdin);
p = freopen("money.out", "w", stdout);
int t = read();
int l, r, mid, ans;
int num, num1, num2;
int sum;
while (t--) {
a = read(), b = read();
c = read(), d = read();
x = read();
l = min(a, c), r = x;
sum = 0;
ans = 0;
while (l <= r) {
mid = (l + r) >> 1;
num = check(mid);
if (num != -1)
l = mid + 1, ans = num, sum = mid;
else
r = mid - 1;
}
num1 = (sum - a) / b + 1, num2 = (sum - c) / d + 1;
if (sum < a)
num1 = 0;
if (sum < c)
num2 = 0;
sum = jsa(num1) + jsc(num2);
if (num1 * b + a + sum <= x || num2 * d + c + sum <= x)
++ans;
write(ans);
printf("\n");
}
return 0;
}
T2
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1801;
int n, p;
int pre[N];
int f[N][10][N];
int g[N][N];
int fm(int y) {
int x = 10, ans = 1;
for (; y; y >>= 1) {
if (y & 1)
ans = ans * x % p;
x = x * x % p;
}
return ans;
}
inline int read() {
int s = 0;
char ch = getchar();
while (ch > '9' || ch < '0') ch = getchar();
while (ch >= '0' && ch <= '9') s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s;
}
int calc(int x) {
int sum = x * x * x, num = sum * x - 1ll;
int loc1, loc2, hd, ws, pos = 1;
num -= sum / 9;
ws = (sum += 2) / 9;
hd = sum % 9 ? sum % 9 : 9;
for (; pos <= ws; ++pos) {
if ((ws - pos + 1) >= num)
break;
num -= ws - pos + 1;
}
loc1 = pos, loc2 = num + pos - 1;
return (1ll * (hd + 1) * fm(ws) % p - 1ll - fm(ws - loc1) - fm(ws - loc2) + 2 * p) % p;
}
signed main() {
FILE* x = freopen("number.in", "r", stdin);
x = freopen("number.out", "w", stdout);
f[0][0][0] = 1, g[0][0] = 1;
for (int ed, i = 1; i <= 1.8e3; ++i) {
for (int k = 0; k <= 1.8e3; ++k) g[i][k] = g[i - 1][k];
for (int j = 1; j <= 9; ++j) {
ed = (i - 1) * 9 + j;
if (ed > (1.8e3))
ed = 1.8e3;
for (int k = j; k <= ed; ++k) {
if (g[i - 1][k - j] > 1e6)
continue;
f[i][j][k] = g[i - 1][k - j];
g[i][k] += f[i][j][k];
}
}
}
n = read(), p = read();
pre[0] = 1;
for (int i = 1; i <= 1.8e3; ++i) pre[i] = pre[i - 1] * 10 % p;
for (int len, k, maxx, sl, ans, now, sum, i = 1; i <= min(n, 12ll); ++i) {
sum = i * i * i, sl = sum * i, ans = 0;
while (sum) {
k = 0, len = 0, maxx = 0;
for (int j = 1; j <= sum; ++j) {
if (k + g[j][sum] >= sl) {
len = j;
break;
}
k = g[j][sum];
}
for (int j = 1; j <= 9; ++j) {
if (k + f[len][j][sum] >= sl) {
maxx = j;
break;
}
k += f[len][j][sum];
}
(ans += maxx * pre[len - 1] % p) %= p;
sl -= k, sum -= maxx;
}
printf("%lld ", ans);
}
for (int i = 13; i <= n; ++i) printf("%lld ", calc(i));
return 0;
}