多校冲刺 NOIP 20211108 模拟 (26)

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;
}

上一篇:行块属性


下一篇:html第二节课