luoguP4491 [HAOI2018]染色 广义容斥原理 + FFT



非常明显的摆了一个NTT模数....

题目中求恰好\(k\),那么考虑求至少\(k\)

记\(g(k)\)表示至少\(k\)中颜色出现了恰好\(S\)次

那么,\[g(k) = \binom{M}{k} \frac{N!}{(S!)^k (N-Sk)!} * (M-k)^{N-Sk}\]

根据广义容斥原理,记\(f(i)\)表示恰好\(k\)种颜色出现了恰好\(k\)次

那么,\[f(i) = \sum \limits_{k = i}^M (-1)^{k - i} \binom{k}{i} g(k)\]

化成卷积式

\[f(i) * i! = \sum \limits_{k = i}^M \frac{(-1)^{k - i}}{(k - i)!} k! g(k)\]

令\(F_i = \frac{(-1)^{i}}{i!}\),\(G_i = i! g(i)\)

记\(H_i\)表示\(f(i) * i\),那么

\[H_i = \sum \limits_{j = i}^M F(k - i) * G(k)\]

反转下标,有

\[H_{n - i}' = \sum \limits_{i = 0}^{n - i} F(k) * G'(n - i - k)\]

\(NTT\)即可,复杂度\(O(n \log n)\)


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)

#define gc getchar
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
    while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

const int sid = 3e5 + 5;
const int cid = 1e7 + 5;
const int mod = 1004535809;

inline int mul(int a, int b) { return 1ll * a * b % mod; }
inline int fp(int a, int k) {
    int ret = 1;
    for( ; k; k >>= 1, a = mul(a, a))
        if(k & 1) ret = mul(ret, a);
    return ret;
}

int N, M, S, n, lg;
int fac[cid], inv[cid];
int rev[sid], f[sid], g[sid], w[sid], W[sid];

inline int C(int n, int m) {
    if(n < m) return 0;
    return mul(fac[n], mul(inv[m], inv[n - m]));
}

inline void NTT(int *a) {
    for(ri i = 0; i < n; i ++)
        if(i < rev[i]) swap(a[i], a[rev[i]]);
    for(ri i = 1; i < n; i <<= 1)
    for(ri j = 0, kj = n / (i << 1); j < n; j += (i << 1))
    for(ri k = j, kp = 0; k < i + j; k ++, kp += kj) {
        int x = a[k], y = mul(w[kp], a[i + k]);
        a[k] = (x + y >= mod) ? x + y - mod : x + y;
        a[i + k] = (x - y < 0) ? x - y + mod : x - y;
    }
}

inline void calc() {
    n = 1; lg = 0;
    while(n <= M + M) n <<= 1, lg ++;
    rep(i, 0, n) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (lg - 1));
    int g_ = fp(3, (mod - 1) / n);
    w[0] = 1;
    rep(i, 1, n) w[i] = mul(w[i - 1], g_);

    int lim = max(N, n);
    fac[0] = fac[1] = inv[0] = inv[1] = 1;
    rep(i, 2, lim) {
        fac[i] = mul(fac[i - 1], i);
        inv[i] = mul(inv[mod % i], mod - mod / i);
    }
    rep(i, 2, lim) inv[i] = mul(inv[i], inv[i - 1]);

    rep(i, 0, M - 1) f[i] = mul(inv[i], (i & 1) ? mod - 1: 1);
    rep(i, 0, M) if(N >= S * i)
        g[i] = 1ll*fac[i]*C(M,i)%mod*fac[N]%mod*fp(inv[S],i)%mod*inv[N-S*i]%mod*fp(M-i,N-S*i)%mod;
    reverse(g, g + M + 1);

    NTT(f); NTT(g);
    rep(i, 0, n) f[i] = mul(f[i], g[i]);
    NTT(f);
    int ivn = fp(n, mod - 2);
    reverse(f + 1, f + n); reverse(f, f + M + 1);
    rep(i, 0, n) f[i] = mul(f[i], mul(ivn, inv[i]));

    int ans = 0;
    rep(i, 0, M) ans = (ans + mul(f[i], W[i])) % mod;
    printf("%d\n", ans);

}

int main() {
    N = read(); M = read(); S = read();
    rep(i, 0, M) W[i] = read();
    calc();
    return 0;
}

原文地址:https://www.cnblogs.com/reverymoon/p/10173833.html

时间: 2024-07-30 15:44:42

luoguP4491 [HAOI2018]染色 广义容斥原理 + FFT的相关文章

bzoj 5306 [HAOI2018] 染色

bzoj 5306 [HAOI2018] 染色 链接 推式子题 首先枚举有几种颜色选择恰好 \(s\) 次,可以得到一个式子: \[\sum _{i = 0} ^ {\min(\frac n s,m )} \frac {\binom n {i \cdot s} \binom m i (i \cdot s) ! \cdot f_i \cdot (m-i)^{n - is}} {(s!) ^ i} \] 但是,\(f_i\) 不能单纯地等于 \(w_i\), 因为会重复计算,我们不能保证当前选择的

【bzoj4487】[Jsoi2015]染色问题 容斥原理

题目描述 棋盘是一个n×m的矩形,分成n行m列共n*m个小方格.现在萌萌和南南有C种不同颜色的颜料,他们希望把棋盘用这些颜料染色,并满足以下规定: 1.  棋盘的每一个小方格既可以染色(染成C种颜色中的一种) ,也可以不染色. 2.  棋盘的每一行至少有一个小方格被染色. 3.  棋盘的每一列至少有一个小方格被染色. 4.  种颜色都在棋盘上出现至少一次. 以下是一些将3×3棋盘染成C = 3种颜色(红.黄.蓝)的例子: 请你求出满足要求的不同的染色方案总数.只要存在一个位置的颜色不同,即认为两

P4491 [HAOI2018]染色

传送门 我觉得自己的数学也是够差的--一点思路也没有-- 考虑容斥,首先\(lim=min(m,n/S)\),设\(f[i]\)表示出现恰好\(S\)次的元素大于等于\(i\)种的情况,我们随便选\(i\)种颜色放\(S\)次,选的方法数有\(C_m^i\)种,然后染色可以看做是一个类似全排列的东西,每连续的几个染上同样的颜色,那么方案数为\(\frac{n!}{(S!)^i(n-S*i)!}\),前面颜色已经选定了,后面的每个有\(m-i\)种颜色可选,所以还要乘上一个\((m-i)^{n-S

[HAOI2018]染色

题目描述 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度为 N 的序列, 每个位置都可以被染成 M 种颜色中的某一种. 然而小 C 只关心序列的 N 个位置中出现次数恰好为 S 的颜色种数, 如果恰 好出现了 S 次的颜色有 K 种, 则小 C 会产生 Wk? 的愉悦度. 小 C 希望知道对于所有可能的染色方案, 他能获得的愉悦度的和对 1004535809取模的结果是多少. 题解 碰到这种等于什么什么的题要考虑容斥. 既然是容斥,那么先设c

HAOI2018 [HAOI2018]染色 【组合数 + 容斥 + NTT】

题目 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度为 \(N\) 的序列, 每个位置都可以被染成 \(M\) 种颜色中的某一种. 然而小 C 只关心序列的 \(N\) 个位置中出现次数恰好为 \(S\) 的颜色种数, 如果恰 好出现了 \(S\) 次的颜色有 \(K\) 种, 则小 C 会产生 \(W_k\) 的愉悦度. 小 C 希望知道对于所有可能的染色方案, 他能获得的愉悦度的和对 1004535809 取模的结果是多少. 输入格式 从

HAOI2018染色——容斥

题目大意 loj 思路 设\(f_i\)表示至少出现了i种颜色的方案数 \[ \begin{aligned} f_i&={m \choose i}\times \frac{(s\times i)!}{(s!)^{i}}\times {n\choose s\times i}\times (m-i)^{n-s\times i}\f_i&={m \choose i}\times \frac{n!}{(s!)^{i}\times (n-s\times i)!}\times (m-i)^{n-s\t

HDU - 6314 Matrix(广义容斥原理)

http://acm.hdu.edu.cn/showproblem.php?pid=6314 题意 对于n*m的方格,每个格子只能涂两种颜色,问至少有A列和B行都为黑色的方案数是多少. 分析 参考https://blog.csdn.net/IcePrincess_1968/article/details/81255138 重点在于计算容斥系数. #include <iostream> #include <cstdio> #include <cstdlib> #inclu

luogu P4491 [HAOI2018]染色

传送门 这一类题都要考虑推式子 首先推出题目要求的式子,枚举正好有\(s\)个颜色的种类(范围\([0,p=min(\lfloor\frac{n}{s}\rfloor,m)]\)),然后对于后面的颜色可能也有数量为\(s\)的,容斥一下即可,即\[ans=\sum_{k=0}^{p}w_k*\binom{m}{k}*\binom{n}{ks}*\frac{(ks)!}{(s!)^k}\sum_{i=0}^{p-k}(-1)^i*\binom{m-k}{i}*\binom{n-ks}{is}*\f

笔记3-28

容斥原理: 错排公式 $f_n=\sum_{i=0}^n(-1)^i\frac{n!}{i!}$=(-1)^n+n*f_{n-1}$ 二项式反演 $b_k=\sum_{i=0}^{k}C_k^ia_i \ \ <--> \ \ a_k=\sum_{i=0}^k(-1)^{k-i}C_k^ib_i$ $b_k=\sum_{i=k}^{n}C_i^ka_i \ \ <--> \ \ a_k=\sum_{i=k}^n(-1)^{i-k}C_i^kb_i$ $*$$n \leq 1e9$个