CF1912J Joy of Pokémon Observation 记录

题目链接:https://codeforces.com/contest/1912/attachments/download/23419/icpc-nerc-2023-statements.pdf

题意简述

求方程 \(\sum \limits_{i =1}^{s} l_i x_i = t\) 的非负整数解的个数。

不多于 \(1024\) 组用例,\(t \le 10^9, s \le 3, l_i \le 16\)

题解(官解)

赛时我光想着怎么求一般方程的解的个数了,没找到什么有用的结果,结果 \(l_i \le 16\) 的条件很重要。

\(s = 1\) 时很显然,若 \(t \equiv 0 \mod l_1\),答案为 \(1\),否则为 \(0\)

\(s = 2\) 时,即求 \(a \cdot i_a + b \cdot i_b = l\) 解的个数。令 \(i_a = k_a \cdot b +j_a\),枚举 \(j_a\),方程变形为 \(k_a \cdot a + i_b = \dfrac{t - a * j_a}{b} := r\)。则在右侧为整数时,需要向答案添加 $\lfloor \dfrac r a \rfloor +1 $,因为对每个 \(k_a \cdot a \le r\),都恰存在一个 \(i_b\)

同理,\(s = 3\) 时,即求 \(a \cdot i_a + b \cdot i_b + c \cdot i_c = l\) 解的个数。令 \(i_a = k_a \cdot c +j_a\)\(i_b = k_b \cdot c +j_b\),枚举 \(j_a\),$ j_b$,则方程转化为 \(k_a \cdot a + k_b \cdot b + i_c = \dfrac {t - a \cdot j_a - b \cdot j_b} {b} := r\)。若右侧为整数,即等于找到 \(k_a \cdot a + k_b \cdot b \le r\) 的解的个数。

再令 \(k_a = r_a \cdot b + e_a\),枚举 \(e_a\),变形为 \(a \cdot r_a + k_b \le \lfloor \dfrac {r - a \cdot e_a} b \rfloor := g\)。枚举 \(r_a\),向答案中加入 \(1 + g - a \cdot r_a\)。枚举 \(r_a\) 的复杂度并不过关,但注意到这部分是一个等差数列,故可以 \(O(1)\) 求解。

单组测试时间复杂度 \(O(l^3)\)

代码实现(C++)

void solve() {
    int n, t;
    cin >> t >> n;
    if (n == 1) {
        int a;
        cin >> a;
        cout << (t % a == 0) << "\n";
    } else if (n == 2) {
        int a, b;
        cin >> a >> b;
        i64 ans = 0;
        for (int ja = 0; ja < b && a * ja <= t; ja++) {
            if ((t - a * ja) % b == 0) {
                int r = (t - a * ja) / b;
                ans += (r / a) + 1;
            }
        }
        cout << ans << "\n";
    } else {
        int a, b, c;
        cin >> a >> b >> c;
        i64 ans = 0;
        for (int ja = 0; ja < c && a * ja <= t; ja++) {
            for (int jb = 0; jb < c && a * ja + b * jb <= t; jb++) {
                if ((t - a * ja - b * jb) % c == 0) {
                    int r = (t - a * ja - b * jb) / c;
                    for (int ea = 0; ea < b && a * ea <= r; ea++) {
                        int g = (r - a * ea) / b;
                        int n = g / a + 1;
                        ans += (i64)(g + g - g / a * a) * n / 2 + n;
                    }
                }
            }
        }
        cout << ans << "\n";
    }
}

posted @ 2023-12-20 00:26  cccpchenpi  阅读(75)  评论(0)    收藏  举报