Luogu 4491 [HAOI2018]染色
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 + ;
const int M = 1e5 + ; 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 = ; i < (int)c.size(); i++)
printf("%lld%c", c[i], " \n"[i == (int)c.size() - ]);
} namespace Poly {
const int L = << ;
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 < ) x += P;
} inline void reverse(poly &c) {
for (int i = , j = (int)c.size() - ; i < j; i++, j--) swap(c[i], c[j]);
} inline ll fpow(ll x, ll y) {
ll res = ;
for (; y > ; y >>= ) {
if (y & ) res = res * x % P;
x = x * x % P;
}
return res;
} inline void prework(int len) {
int l = ;
for (lim = ; lim < len; lim <<= , ++l);
for (int i = ; i < lim; i++)
pos[i] = (pos[i >> ] >> ) | ((i & ) << (l - ));
} inline void ntt(poly &c, int opt) {
c.resize(lim, );
for (int i = ; i < lim; i++)
if (i < pos[i]) swap(c[i], c[pos[i]]);
for (int i = ; i < lim; i <<= ) {
ll wn = fpow(, (P - ) / (i << ));
if (opt == -) wn = fpow(wn, P - );
for (int len = i << , j = ; j < lim; j += len) {
ll w = ;
for (int k = ; 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 == -) {
ll inv = fpow(lim, P - );
for (int i = ; 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() - );
ntt(u, ), ntt(v, );
for (int i = ; i < lim; i++) res.push_back(u[i] * v[i] % P);
ntt(res, -);
res.resize(x.size() + y.size() - );
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 = ; char ch = ; T op = ;
for (; ch > ''|| ch < ''; ch = getchar())
if (ch == '-') op = -;
for (; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void prework(int len) {
fac[] = ;
for (int i = ; i <= len; i++) fac[i] = fac[i - ] * i % P;
ifac[len] = fpow(fac[len], P - );
for (int i = len - ; i >= ; i--) ifac[i] = ifac[i + ] * (i + ) % 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 = ; i <= m; i++) read(w[i]); int rep = min(m, n / s);
prework(max(n, m)); for (int i = ; 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 + , ), b.resize(rep + , );
for (int i = ; i < rep + ; i++) {
a[i] = f[i] * fac[i] % P;
b[i] = ifac[i];
if (i & ) 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 = ;
for (int i = ; i <= rep; i++) {
g[i] = ifac[i] * c[rep + i] % P;
inc(ans, w[i] * g[i] % P);
} printf("%lld\n", ans);
return ;
}
Luogu 4491 [HAOI2018]染色的更多相关文章
- luogu P4491 [HAOI2018]染色
传送门 这一类题都要考虑推式子 首先推出题目要求的式子,枚举正好有\(s\)个颜色的种类(范围\([0,p=min(\lfloor\frac{n}{s}\rfloor,m)]\)),然后对于后面的颜色 ...
- [洛谷P4491] [HAOI2018]染色
洛谷题目链接:[HAOI2018]染色 题目背景 HAOI2018 Round2 第二题 题目描述 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度 ...
- [BZOJ5306] [HAOI2018]染色(容斥原理+NTT)
[BZOJ5306] [HAOI2018]染色(容斥原理+NTT) 题面 一个长度为 n的序列, 每个位置都可以被染成 m种颜色中的某一种. 如果n个位置中恰好出现了 S次的颜色有 K种, 则小 C ...
- BZOJ 5306 [HAOI2018] 染色
BZOJ 5306 [HAOI2018] 染色 首先,求出$N$个位置,出现次数恰好为$S$的颜色至少有$K$种. 方案数显然为$a_i=\frac{n!\times (m-i)^{m-i\times ...
- 【BZOJ5306】 [Haoi2018]染色
BZOJ5306 [Haoi2018]染色 Solution xzz的博客 代码实现 #include<stdio.h> #include<stdlib.h> #include ...
- 【LG4491】[HAOI2018]染色
[LG4491][HAOI2018]染色 题面 洛谷 题解 颜色的数量不超过\(lim=min(m,\frac nS)\) 考虑容斥,计算恰好出现\(S\)次的颜色至少\(i\)种的方案数\(f[i] ...
- [Luogu 2486] SDOI2011 染色
[Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...
- Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)
Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...
- 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)
[题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...
随机推荐
- python3 openpyxl基本操作
#coding:utf-8 import xlrd import xlwt # 读写2007 excel import openpyxl import sys #读取设备sn # def readSN ...
- java对图片的处理
原文地址:http://www.blogjava.net/PrettyBoyCyb/archive/2006/11/13/80922.html java 中的图片处理是很让人头疼的一件事情.目前 ja ...
- node使用JsonWebToken 生成token,完成用户登录、登录检测
最近在用node做后台的登录,检测登录功能.在本地使用session可以成功,但是放服务器后发现session失效了,每次请求session都会变化,着了很久原因.原来,自己项目是前后端分离的,前端调 ...
- bzo j4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...
- 关于ROS的MANGLE和ip route-rules-lookup的关系和区别
mangle打出来的mark routing的优先级和lookup打出来的优先级是一样的.(你可以这么理解,lookup根据目的地址打出来的标签,其实跟在ip firewall-mangle打出来的是 ...
- Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?)
ubuntu16在运行sudo apt-get update 命令后,报出错误: Clearsigned file isn't valid, got 'NOSPLIT' (does the netwo ...
- 【POJ】2778 DNA Sequence(AC自动机+矩阵快速幂)
题目 传送门:QWQ 分析 对着Trie图搞快速幂. 为什么这样是对的呢? 详见:http://www.matrix67.com/blog/archives/276 有些地方还不是很理解......为 ...
- linux记录每个用户执行的命令
1.在/etc/profile中添加如下代码: #history USER_IP=`>/dev/null| awk '{print $NF}'|sed -e 's/[()]//g'` HISTD ...
- maven settings.xml 文件
指定jdk 的版本: <profile> <id>jdk-1.8</id> <activation> <activeByDefault>tr ...
- SQL Server数据库partition by 与ROW_NUMBER()函数使用详解[转]
关于SQL的partition by 字段的一些用法心得 先看例子: if object_id('TESTDB') is not null drop table TESTDB create table ...