YZOI p278

赛时把正解复杂度算成 \(\mathcal{O}(n^{10000}\log V)\) 了遗憾离场了qwq,这里不赘述正解做法,给出一个赛后看到的爆标做法。

首先考虑每个位置的操作次数为 \(c_i = 3k + a_i, a_i \in [0, 2]\),总操作次数的限制是 \(N\),那么贡献就是 \(\frac{(\sum c_i)!}{\prod c_i!}\),即多重组合数。那么容易想到用 EGF 来刻画。

\([x^i]\hat F_j(x)\)\(j\) 这个位置操作 \(i\) 次的方案数。

\[\hat F_j(x) = \sum\limits_{i \ge 0} \dfrac{x^{3i+a_j}}{(3i+a_i)!} \]

\[=\sum\limits_{i \ge 0} [i \bmod 3 = a_j]\dfrac{x^i}{i!} \]

\[\sum\limits_{i \ge 0}[3 \mid (i - a_j)] \dfrac{x^i}{i!} \]

单位根反演得

\[\sum\limits_{i \ge 0}\dfrac{1}{3}\sum\limits_{k=0}^2 \omega_3^{k(i-a_j)}\dfrac{x^i}{i!} \]

\[=\dfrac{1}{3}\sum\limits_{k=0}^2\dfrac{1}{\omega_3^{ka_j}}\sum\limits_{i\ge0}\omega_3^{ki}\dfrac{x^i}{i!} \]

然后答案就是 \(\sum\limits_{i=0}^N [x^i]\hat G(x)\),其中 \(\hat G(x) = \prod \hat F(x)\)

\[\hat G(x) = \prod\hat F(x) \]

\[=\dfrac{1}{3^n}\prod\limits_{j=1}^n \sum\limits_{k=0}^2\dfrac{1}{\omega_3^{ka_j}}\sum\limits_{i\ge0}\omega_3^{ki}\dfrac{x^i}{i!} \]

\[=\dfrac{1}{3^n}\prod\limits_{j=1}^n \sum\limits_{k=0}^2\omega_3^{-ka_j}e^{\omega_3^{ki}x} \]

后面的部分直接展开,得到

\[e^x + \omega^{-a_i}e^{\omega x} + \omega^{-2a_i}e^{\omega^2x} \]

那么若干个这种形式乘起来会得到若干 \(pe^{qx}\) 的形式,展开,

\[pe^{qx} = \sum\limits_{i \ge 0} \dfrac{pq^ix_i}{i!} \]

对 EGF 的系数求前缀和:

\[\sum\limits_{i=0}^N pq^i=p\dfrac{q^{N+1}-1}{q-1} \]

最后的系数用递推计算即可,时间复杂度 \(\mathcal{O}(n^3 \log mod)\)

namespace Loop1st {
int n, a[15], cost[3];
char s[15], t[15];
ll m;
struct Complex {
    ll x, y;
    Complex(ll _x = 0, ll _y = 0): x(_x), y(_y) {}
    Complex operator + (const Complex &A) const { return Complex((x + A.x) % mod, (y + A.y) % mod); }
    void operator += (const Complex &A) { *this = *this + A; }
    Complex operator * (const Complex &A) const { return Complex(((x * A.x - y * A.y) % mod + mod) % mod, (x * A.y + y * A.x) % mod); }
    void operator *= (const Complex &A) { *this = *this * A; }
    void operator = (const ll &A) { *this = Complex(A % mod, 0); }
} f[15][15], g[15][15];
const Complex w((mod - 1) >> 1, (mod + sq3) >> 1), w2((mod - 1) >> 1, (mod - sq3) >> 1);
ll qpow(ll a, ll b) {
    ll res = 1;
    for (; b; b >>= 1, a = a * a % mod) if (b & 1) res = res * a % mod;
    return res;
}
ll inv(ll x) { return qpow(x, mod - 2); }
Complex inv(Complex A) {
    ll div = inv((A.x * A.x + A.y * A.y) % mod);
    return Complex(A.x * div % mod, (mod - A.y) * div % mod);
}
Complex qpow(Complex a, ll b) {
    Complex res = 1;
    if (b < 0) a = inv(a), b = -b;
    for (; b; b >>= 1, a = a * a) if (b & 1) res = res * a;
    return res;
}
Complex calc(Complex q, ll k) {
    if (q.x == 1 && q.y == 0) return Complex(k + 1, 0);
    return (qpow(q, k + 1) + Complex(mod - 1, 0)) * inv(q + Complex(mod - 1, 0));
}

void Main(int tc) {
    cin >> s >> t >> cost[0] >> cost[1] >> cost[2] >> m;
    n = strlen(s);
    Complex ans(qpow(iv3, n), 0);
    ll N = 0;
    for (int i = 0; i < n; i++) {
        while (s[i] != t[i]) {
            m -= cost[s[i] - 'a'];
            s[i] = 'a' + (s[i] - 'a' + 1) % 3;
            a[i]++;
        }
        N += a[i];
    }
    if (m < 0) { cout << "0\n"; return ; }
    N += m / (cost[0] + cost[1] + cost[2]) * 3;
    f[0][0] = 1;
    for (int i = 0; i < n; i++) {
        memset(g, 0, sizeof g);
        for (int j = 0; j <= i; j++) {
            for (int k = 0; k <= i - j; k++) {
                g[j + 1][k] += f[j][k];
                g[j][k + 1] += qpow(w, -a[i]) * f[j][k];
                g[j][k] += qpow(w, -2 * a[i]) * f[j][k];
            }
        }
        memcpy(f, g, sizeof f);
    }

    Complex res;
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= n - i; j++) {
            Complex q = Complex(i, 0) + Complex(j, 0) * w + Complex(n - i - j, 0) * w2;
            res += f[i][j] * calc(q, N);
        }
    }
    ans *= res;
    cout << ans.x << '\n';
}

}
posted @ 2026-04-26 19:42  循环一号  阅读(6)  评论(0)    收藏  举报