BZOJ 5306

考虑计算恰好出现$s$次的颜色有$k$种的方案数。

首先可以设$lim = min(m, \left \lfloor \frac{n}{s} \right \rfloor)$,我们在计算的时候只要算到这个$lim$就可以了。

设$f(k)$表示出现$s$次的颜色至少有$k$种的方案数,则

$$f(k) = \binom{m}{k}\binom{n}{ks}\frac{(ks)!}{(s!)^k}(m - k)^{n - ks}$$

就是先选出$k$个颜色和$ks$个格子放这些颜色,这样子总的方案数是全排列除以限排列,剩下的颜色随便放。

处理一下组合数,整个$f$可以在$O(nlogn)$时间内算出来。

设$g(k)$表示出现$s$次的颜色刚好有$k$种的方案数,考虑到对于$\forall i < j$,$g(j)$在$f(i)$中被计算了$\binom{j}{i}$次,所以有

$$f(k) = \sum_{i = k}^{lim}\binom{i}{k}g(i)$$

直接二项式反演回来,

$$g(k) = \sum_{i = k}^{lim}(-1)^{i - k}\binom{i}{k}f(i)$$

拆开组合数,

$$g(k) = \sum_{i = k}^{lim}(-1)^{i - k}\frac{i!}{k!(i - k)!}f(i) = \frac{1}{k!}\sum_{i = k}^{lim}\frac{(-1)^{i - k}}{(i - k)!}(f(i) * (i!))$$

设$A(i) = f(i) * (i!)$,$B(i) = \frac{(-1)^{i}}{i!}$

$$g(k)* (k!) = \sum_{i = k}^{lim}A(i)B(i - k)$$

咕,并不是卷积。

把$B$翻转,再设$B'(i) = B(lim - i)$

$$g(k)* (k!) = \sum_{i = k}^{lim}A(i)B'(lim + k - i)$$

注意到$A*B'$的第$lim + k$项的系数是$\sum_{i = 0}^{lim + k}A(i)B'(lim + k - i)$,但是需要满足

$$ 0 \leq i \leq lim$$

$$ 0 \leq lim + k - i \leq lim $$

$$k \leq i \leq lim$$

刚好满足。

时间复杂度$O(n + mlogm)$。

Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
typedef vector <ll> poly;const int N = 1e7 + 5;
const int M = 1e5 + 5;int n, m, s;
ll w[M], fac[N], ifac[N], f[M], g[M], sum[M];inline void deb(poly c) {for (int i = 0; i < (int)c.size(); i++)printf("%lld%c", c[i], " \n"[i == (int)c.size() - 1]);
}namespace Poly {const int L = 1 << 18;const ll P = 1004535809LL;int lim, pos[L];template <typename T>inline void inc(T &x, T y) {x += y;if (x >= P) x -= P;}template <typename T>inline void sub(T &x, T y) {x -= y;if (x < 0) x += P;}inline void reverse(poly &c) {for (int i = 0, j = (int)c.size() - 1; i < j; i++, j--) swap(c[i], c[j]);}inline ll fpow(ll x, ll y) {ll res = 1;for (; y > 0; y >>= 1) {if (y & 1) res = res * x % P;x = x * x % P;}return res;}inline void prework(int len) {int l = 0;for (lim = 1; lim < len; lim <<= 1, ++l);for (int i = 0; i < lim; i++)pos[i] = (pos[i >> 1] >> 1) | ((i & 1) << (l - 1));}inline void ntt(poly &c, int opt) {c.resize(lim, 0);for (int i = 0; i < lim; i++)if (i < pos[i]) swap(c[i], c[pos[i]]);for (int i = 1; i < lim; i <<= 1) {ll wn = fpow(3, (P - 1) / (i << 1));if (opt == -1) wn = fpow(wn, P - 2);for (int len = i << 1, j = 0; j < lim; j += len) {ll w = 1;for (int k = 0; k < i; k++, w = w * wn % P) {ll x = c[j + k], y = c[j + k + i] * w % P;c[j + k] = (x + y) % P, c[j + k + i] = (x - y + P) % P;}}}if (opt == -1) {ll inv = fpow(lim, P - 2);for (int i = 0; i < lim; i++) c[i] = c[i] * inv % P;}}inline poly mul(const poly x, const poly y) {poly u = x, v = y, res;prework(x.size() + y.size() - 1);ntt(u, 1), ntt(v, 1);for (int i = 0; i < lim; i++) res.push_back(u[i] * v[i] % P);ntt(res, -1);res.resize(x.size() + y.size() - 1);return res;}}using Poly :: P;
using Poly :: fpow;
using Poly :: mul;
using Poly :: inc;
using Poly :: reverse;template <typename T>
inline void read(T &X) {X = 0; char ch = 0; T op = 1;for (; ch > '9'|| ch < '0'; ch = getchar())if (ch == '-') op = -1;for (; ch >= '0' && ch <= '9'; ch = getchar())X = (X << 3) + (X << 1) + ch - 48;X *= op;
}inline void prework(int len) {fac[0] = 1;for (int i = 1; i <= len; i++) fac[i] = fac[i - 1] * i % P;ifac[len] = fpow(fac[len], P - 2);for (int i = len - 1; i >= 0; i--) ifac[i] = ifac[i + 1] * (i + 1) % P;
}inline ll getC(int x, int y) {return fac[x] * ifac[y] % P * ifac[x - y] % P;
}int main() {read(n), read(m), read(s);for (int i = 0; i <= m; i++) read(w[i]);int rep = min(m, n / s);prework(max(n, m));for (int i = 0; i <= rep; i++) f[i] = getC(m, i) * getC(n, i * s) % P * fac[i * s] % P * fpow(ifac[s], i) % P * fpow(m - i, n - i * s) % P;/*    for (int i = 0; i <= rep; i++)printf("%lld%c", f[i], " \n"[i == rep]);     */poly a, b;a.resize(rep + 1, 0), b.resize(rep + 1, 0);for (int i = 0; i < rep + 1; i++) {a[i] = f[i] * fac[i] % P;b[i] = ifac[i];if (i & 1) b[i] = (P - b[i]) % P;} reverse(b);//    deb(a), deb(b);
    poly c = mul(a, b);//    deb(c);/*    for (int i = rep; i >= 0; i--) {sum[i] = sum[i + 1];inc(sum[i], c[i]);}   for (int i = 0; i <= rep; i++)printf("%lld%c", sum[i], " \n"[i == rep]);    */ ll ans = 0;for (int i = 0; i <= rep; i++) {g[i] = ifac[i] * c[rep + i] % P;inc(ans, w[i] * g[i] % P);}printf("%lld\n", ans);return 0;
}

View Code

转载于:https://www.cnblogs.com/CzxingcHen/p/10290551.html

Luogu 4491 [HAOI2018]染色相关推荐

  1. [Luogu 2486] SDOI2011 染色

    [Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...

  2. P4491 [HAOI2018]染色

    反思 二项式反演的板子,但是还要加上一个NTT,就变得恶心人了 我NTT写挂调了好长时间... 注意 NTT应该这么写 int tmp=pow((opt)?invG:G,(MOD-1)/i); 而不这 ...

  3. [HAOI2018]染色

    题解 我竟然能自己想出来计数题 容斥+NTT 首先一看到题目让求恰好出现\(S\)次的颜色有恰好\(K\)种就想到容斥 如果容斥每种颜色出现次数的话并不好计数 那么考虑容斥恰好出现\(S\)次的颜色有 ...

  4. HAOI2018 染色

    传送门 一道非常好的容斥+NTT,对我这样的菜鸡难度稍高. 符合要求的颜色最多有\(lim = min(m,\lfloor\frac{n}{S}\rfloor)\)种. 首先,考虑恰好出现S次不是很容 ...

  5. [HAOI2018] 染色(二项式反演+NTT)

    洛谷链接 显然颜色数量不会超过 lim⁡=min⁡(m,ns)\lim=\min(m,\frac ns)lim=min(m,sn​) fi:f_i:fi​: 至少有 iii 种颜色恰好出现了 sss ...

  6. PKUWC2019游记

    PKUWC2019游记 \(Day\) 很久之前 听说 \(440\) 能去 \(PKUWC\),惊喜啊!其实就是为期末考爆炸找个借口 最近感觉学了不少东西.虽然 \(PKUWC\) 的题目以组合和数 ...

  7. Luogu P3177 [HAOI2015] 树上染色(树上背包)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Luogu P3177 [HAOI2015] 树上染色 有一棵点数为 NNN 的树,树边有边权.给你一 ...

  8. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  9. 【树链剖分】染色(luogu 2486/金牌导航 树链剖分-3)

    正题 luogu 2486 金牌导航 树链剖分-3 题目大意 给你一棵树,让你进行以下操作: 1.把一条路径染上一个颜色 2.查询一条路径上有多少个颜色段 解题思路 用树链剖分把问题转化为链上问题 然 ...

最新文章

  1. 鸿蒙开发者自学,【5月21日鸿蒙公开课】自学鸿蒙 当代大学生的进阶之路
  2. 射影几何3:拓广平面
  3. (转)探究 TCP 一次数据包最大负载,上限真的是 65495 byte 吗
  4. 速度收藏!600页阿里技术全景图曝光,程序员看完都沸腾了
  5. IDEA配置git环境
  6. java aspose重叠_Aspose.Words - 在特定位置合并两个文档
  7. 改变WCF service location的 hostName
  8. yarn当中各个主要组件的作用及调度器
  9. .htaccess文件玩转Rewrite
  10. android view 画文字,【Android自定义View】绘图之文字篇(三)
  11. 【leetcode刷题】[简单]427. 建立四叉树(construct quad tree)-java
  12. ipv4和计算机地址是什么意思,ipv6是什么意思?我们怎么查看电脑iPv6地址
  13. UA用Mode-Driven的使用笔记
  14. Win10系统更新完之后,电脑短时间内自动睡眠问题:解决.
  15. opencv:图像的读取和显示
  16. ASP一个小型搜索引擎的设计与实现
  17. PostgreSQL 别名
  18. Chapter7 循环神经网络-2
  19. iMindMap Android中字体格式该怎么进行修改
  20. 15 PyAutoGUI 键盘控制函数(2)

热门文章

  1. 高效!Anchor DETR:旷视提出一种基于Transformer的目标检测神器!
  2. 李沐分享斯坦福2021秋季新课:实用机器学习
  3. 深度学习三(PyTorch物体检测实战)
  4. 大数据分析实战-信用卡欺诈检测
  5. python字符串只留数字_Python数字和字符串(5/30)
  6. java 的进程_windows 启动停止 java进程
  7. webassembly类型_WebAssembly 现状与实战
  8. Java 面试之线程与锁
  9. elementui带输入建议查询_elementUi简单实现搜索提词功能
  10. python的repl模式_如何更改sublimeREPL默认python版本