ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 [HAOI2018] 染色

2022-02-22 09:03:28  阅读:161  来源: 互联网

标签:frac 题解 sum times sj 染色 binom HAOI2018 LL


题目链接

Luogu
Loj

题目描述

对一个长度为 \(n\) 的序列染色,颜色一共有 \(m\) 种,对于每一种染色方案,设有 \(u\) 种颜色恰好出现了 \(s\) 次,则将答案加 \(w_u\) ,求答案
其中 \(n \leq 10^7, m \leq 10^5, s \leq 150\),并将答案对 \(1004535809\) 取模

分析

下面的式子虽然有点多,但每一步推导都非常简单,应该可以在不使用草稿纸的情况下看懂

首先,\(1004535809\) 的出现直接暗示了我们这题需要 NTT

然后肯定就是生成函数推柿子题了

考虑枚举恰好出现了 \(s\) 次的颜色有多少种

就假设枚举到 \(i\) 种

那么对于这 \(i\) 种颜色,他们的指数型生成函数都是

\[\frac{x^s}{s!} \]

那对于另外的 \(m - i\) 种颜色,由于他们不能恰好出现 \(s\) 次,那他们的生成函数就应该是

\[\begin{equation} \begin{split} F(x) &= \frac{x^0}{0!} + \frac{x^1}{1!} + \frac{x^2}{2!} + \frac{x^3}{3!} + ... - \frac{x^s}{s!}\\ &= \sum_{k \ge 0} \frac{x^k}{k!} - \frac{x^s}{s!}\\ &= e^x - \frac{x^s}{s!} \end{split} \end{equation} \]

那么,假设选定了 \(i\) 种颜色使他们恰好出现 \(s\) 次,这样的序列个数就是

\[n! \times [x^n](\frac{x^s}{s!})^i (e^x - \frac{x^s}{s!})^{m - i} \]

这个 \(n!\) 是因为这是指数型生成函数

再考虑从 \(m\) 种颜色中选出 \(i\) 种颜色作为恰好出现 \(s\) 次的颜色的方案数,所以答案就是

\[\begin{equation} \begin{split} ans &= \sum_{i = 0}^m w_i \times \binom{m}{i} \times n! \times [x^n](\frac{x^s}{s!})^i (e^x - \frac{x^s}{s!})^{m - i}\\ &= \sum_{i = 0}^m w_i \times \binom{m}{i} \times \frac{n!}{(s!)^i} \times [x^n]x^{si} (e^x - \frac{x^s}{s!})^{m - i}\\ &= \sum_{i = 0}^m w_i \times \binom{m}{i} \times \frac{n!}{(s!)^i} \times [x^{n - si}] (e^x - \frac{x^s}{s!})^{m - i}\\ \end{split} \end{equation} \]

对于最后那一项,我们用二项式定理展开,有

\[(e^x - \frac{x^s}{s!})^{m - i} = \sum_{j = 0}^{m - i} (-1)^j \frac{x^{sj}}{(s!)^j} e^{x(m-i-j)} \binom{m-i}{j} \]

代入得答案为

\[ans = \sum_{i = 0}^m w_i \times \binom{m}{i} \times \frac{n!}{(s!)^i} \times [x^{n - si}] \sum_{j = 0}^{m - i} (-1)^j \frac{x^{sj}}{(s!)^j} e^{x(m-i-j)} \binom{m-i}{j}\\ \]

这里观察到如果 \(j\) 从 \(i\) 开始枚举的话式子会简单许多

\[ans = \sum_{i = 0}^m w_i \times \binom{m}{i} \times \frac{n!}{(s!)^i} \times [x^{n - si}] \sum_{j = i}^{m} (-1)^{j-i} \frac{x^{s(j-i)}}{(s!)^{j-i}} e^{x(m-j)} \binom{m-i}{j-i} \]

把 \(\frac{1}{(s!)^i}\) 和 \([x^{n - si}]\) 写进去

\[\begin{equation} \begin{split} ans &= \sum_{i = 0}^m w_i \times \binom{m}{i} \times n! \times \sum_{j = i}^{m} [x^{n - sj}] (-1)^{j-i} \frac{1}{(s!)^j} e^{x(m-j)} \binom{m-i}{j-i}\\ &=\sum_{i = 0}^m w_i \times \binom{m}{i} \times n! \times \sum_{j = i}^{m} (-1)^{j-i} \frac{1}{(s!)^j} \binom{m-i}{j-i} [x^{n - sj}] e^{x(m-j)} \end{split} \end{equation} \]

而我们又知道

\[e^{kx} = \sum_{i \ge 0} \frac{k^i s^i}{i!} \]

所以

\[[x^{n - sj}] e^{x(m-j)} = \frac{(m-j)^{n-sj}}{(n-sj)!} \]

代进去

\[ans = \sum_{i = 0}^m w_i \times \binom{m}{i} \times n! \times \sum_{j = i}^{m} (-1)^{j-i} \frac{1}{(s!)^j} \binom{m-i}{j-i} \frac{(m-j)^{n-sj}}{(n-sj)!} \]

观察发现两个二项式系数显然可以消掉一个阶乘,于是我们把二项式系数展开

\[ans = \sum_{i = 0}^m w_i \times \frac{m!}{i!} \times n! \times \sum_{j = i}^{m} (-1)^{j-i} \frac{1}{(s!)^j} \frac{1}{(j-i)!(m-j)!} \frac{(m-j)^{n-sj}}{(n-sj)!} \]

其实到这里已经差不多可以看出来了,我们再变形一下

\[ans = \sum_{i = 0}^m w_i \times \frac{m!}{i!} \times n! \times \sum_{j = i}^{m} \frac{(-1)^{j-i}}{(j-i)!} \times \frac{(m-j)^{n-sj}}{(s!)^j(m-j)!(n-sj)!} \]

可以发现 \(\frac{(-1)^{j-i}}{(j-i)!}\) 的取值只与 \(j-i\) 有关,\(\frac{(m-j)^{n-sj}}{(s!)^j(m-j)!(n-sj)!}\) 只与 \(j\) 有关
我们分别将其设为 \(g_{j-i}\) 与 \(f_j\)

那么

\[ans = \sum_{i = 0}^m w_i \times \frac{m!}{i!} \times n! \times \sum_{j = i}^{m} f_j \times g_{j-i} \]

可以发现这里有一个极其类似卷积的式子,对于这样的式子,我们的操作是将 \(f\) 翻转,即让 \(f_j\) 与 \(f_{m-j}\) 交换,那么对于新的 \(f_j\),他对应的原来的 \(f\) 值就是 \(f_{m-j}\),所以他应该乘的 \(g\) 值就是 \(g_{m-j-i}\),到这里卷积的形式就出来了

我们再写一遍答案

\[\begin{equation} \begin{split} ans &= \sum_{i = 0}^m w_i \times \frac{m!}{i!} \times n! \times \sum_{j = 0}^{m-i} f_j \times g_{m-j-i}\\ &= n!m! \sum_{i = 0}^m \frac{w_i}{i!} \sum_{j = 0}^{m-i} f_j \times g_{m-j-i} \end{split} \end{equation} \]

其中

\[f_i = \frac{(-1)^{m-i}}{(m-i)!}\\ g_i = \frac{(m-i)^{n-si}}{(s!)^i(m-i)!(n-si)!} \]

如果 \(n-si < 0\) 则令 \(f_i = 0\) 即可

使用 NTT 求解卷积,复杂度为 \(O(n + m\log m)\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N = 1e7 + 10;
const int M = 400010;
const LL p = 1004535809;

LL n, m, s, ge = 3, ig, mx = 1, ans, w[M], f[M], g[M], fac[N];

LL ksm(LL v, LL tms)
{
    LL res = 1;
    for(; tms; tms >>= 1, v = v * v % p) if(tms & 1) res = res * v % p;
    return res;
}

void NTT(LL *a, LL mx, LL flag)
{
    for(int i = 0, j = 0; i < mx; i++){
        if(i < j) swap(a[i], a[j]);
        for(int l = mx >> 1; (j ^= l) < l; l >>= 1);
    }
    for(int i = 2; i <= mx; i <<= 1){
        LL now = (i >> 1), step = ksm((flag > 0 ? ge : ig), (p - 1) / i);
        for(int j = 0; j < mx; j += i){
            LL temp = 1;
            for(int k = 0; k < now; k++){
                LL G = a[j + k], H = temp * a[j + k + now] % p;
                a[j + k] = (G + H) % p, a[j + k + now] = (G - H + p) % p;
                temp = step * temp % p;
            }
        }
    }
    LL inv = ksm(mx, p - 2);
    if(flag < 0) for(int i = 0; i < mx; i++) a[i] = a[i] * inv % p;
}

int main()
{
    ios :: sync_with_stdio(false), cin.tie(0);
    ig = ksm(ge, p - 2);
    cin >> n >> m >> s;
    for(int i = 0; i <= m; i++) cin >> w[i];

    fac[0] = 1;
    for(int i = 1; i <= max(n, m); i++) fac[i] = fac[i - 1] * i % p;

    for(int i = 0; i <= m; i++)
        g[i] = (((i & 1) ? -1 : 1) * ksm(fac[i], p - 2) + p) % p;
    for(int i = 0; i <= m; i++)
        if(s * i > n) f[i] = 0; //特判f[i]=0
        else f[i] = ksm((ksm(fac[s], i) * fac[m - i] % p) * fac[n - s * i] % p, p - 2) * ksm(m - i, n - s * i) % p;
    for(int i = 0; (i << 1) <= m; i++) swap(f[i], f[m - i]); //翻转f

    while(mx <= m) mx <<= 1; mx <<= 1;
    NTT(f, mx, 1);
    NTT(g, mx, 1);
    for(int i = 0; i < mx; i++) f[i] = f[i] * g[i] % p;
    NTT(f, mx, -1);

    for(int i = 0; i <= m; i++)
        if(s * i <= n) ans = (ans + ((w[i] * ksm(fac[i], p - 2) % p) * f[m - i] % p) + p) % p;
    ans = ans * (fac[n] * fac[m] % p) % p;
    printf("%lld\n", ans);
    return 0;
}

标签:frac,题解,sum,times,sj,染色,binom,HAOI2018,LL
来源: https://www.cnblogs.com/sgweo8yspace/p/15920895.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有