题目链接  2017 CCPC Hangzhou Problem G

题意描述很清晰。

考虑每个家庭有且仅有$k$对近亲的方案数:

$C(a, k) * C(b, k) * k!$

那么如果在第$1$个家庭里面选出$k_{1}$对近亲,在第$2$个家庭里面选出$k_{2}$对近亲......在第$n$个家庭里面选出$k_{n}$对近亲,

剩下那些人自由组合的话,那么最后这种方案至少会有$∑k$对近亲。

说是至少,因为同一个家庭里面没被强行选择的男女还是可能被组到了一起。

那么考虑如何求至少有$k$对近亲的方案数。

构造$n$个多项式,对于每个家庭,这个多项式为

$c_{0} + c_{1}x + c_{2}x^{2} + c_{3}x^{3} + c_{4}x^{4} + ... + c_{p}x^{p}$, $p = min(a, b)$

其中$c_{i}$这个系数为在这个家庭里面选出$i$对近亲的方案数。

那么只要把这$n$个多项式乘起来,得到的结果里面$x^{k}$的系数就是至少有$k$对近亲的方案数。

把$n$个多项式求出来用分治NTT即可,我用了启发式合并。

因为是至少,所以还要考虑容斥。

最后的答案就是$(-1)^{k}a_{k} * (m - k)!$,$m$为总人数

时间复杂度$O(nlog^{2}n)$

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)    for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef long long LL; const int N = 1e5 + 10;
const LL mod = 998244353;
const LL g = 3; vector <LL> v[N << 1];
LL x1[N << 1], x2[N << 1];
LL fac[N];
LL ans, flag;
int T;
int n, all, cnt;
int sz; inline LL Pow(LL a, LL b, LL mod){
LL ret(1);
for (; b; b >>= 1, (a *= a) %= mod) if (b & 1) (ret *= a) %= mod;
return ret;
} inline LL C(LL n, LL m){ return m > n ? 0 : fac[n] * Pow(fac[m] * fac[n - m] % mod, mod - 2, mod) % mod; } struct cmp{
bool operator ()(int a, int b){
return v[a].size() > v[b].size();
}
}; priority_queue <LL, vector <LL>, cmp> q; void change(LL y[], int len){
for (int i = 1, j = len / 2; i < len - 1; i++){
if (i < j) swap(y[i], y[j]);
int k = len / 2;
while (j >= k){
j -= k;
k /= 2;
}
if (j < k) j += k;
}
} void ntt(LL y[], int len, int on){
change(y, len);
for (int h = 2; h <= len; h <<= 1){
LL wn = Pow(g, (mod - 1) / h, mod);
if (on == -1) wn = Pow(wn, mod - 2, mod);
for (int j = 0; j < len; j += h){
LL w = 1ll;
for (int k = j; k < j + h / 2; k++){
LL u = y[k];
LL t = w * y[k + h / 2] % mod;
y[k] = (u + t) % mod;
y[k + h / 2] = (u - t + mod) % mod;
w = w * wn % mod;
}
}
} if (on == -1){
LL t = Pow(len, mod - 2, mod);
rep(i, 0, len - 1) y[i] = y[i] * t % mod;
}
} void mul(vector <LL> &a, vector <LL> &b, vector <LL> &c){
int len = 1;
int sz1 = a.size(), sz2 = b.size(); while (len <= sz1 + sz2 - 1) len <<= 1; rep(i, 0, sz1 - 1) x1[i] = a[i];
rep(i, sz1, len) x1[i] = 0; rep(i, 0, sz2 - 1) x2[i] = b[i];
rep(i, sz2, len) x2[i] = 0; ntt(x1, len, 1);
ntt(x2, len, 1); rep(i, 0, len - 1) x1[i] = x1[i] * x2[i]; ntt(x1, len, -1); vector <LL>().swap(c);
rep(i, 0, sz1 + sz2 - 2) c.push_back(x1[i]);
} int main(){ fac[0] = 1;
rep(i, 1, 1e5 + 3) fac[i] = fac[i - 1] * i % mod; scanf("%d", &T); while (T--){
scanf("%d", &n);
rep(i, 0, n + 1) vector <LL>().swap(v[i]); while (!q.empty()) q.pop(); all = 0; rep(i, 1, n){
int x, y;
scanf("%d%d", &x, &y);
v[i].resize(min(x, y) + 1);
rep(k, 0, min(x, y)) v[i][k] = C(x, k) * C(y, k) % mod * fac[k] % mod;
q.push(i);
all += x;
} cnt = n;
rep(i, 1, n - 1){
int x = q.top(); q.pop();
int y = q.top(); q.pop(); mul(v[x], v[y], v[++cnt]); vector <LL>().swap(v[x]);
vector <LL>().swap(v[y]); q.push(cnt);
} ans = 0;
flag = 1;
sz = (int)v[cnt].size();
rep(i, 0, sz - 1){
ans = ans + flag * fac[all - i] % mod * v[cnt][i] % mod;
ans = (ans + mod) % mod;
flag = -flag;
} printf("%lld\n", ans);
} return 0;
}

HDU 6270 Marriage (2017 CCPC 杭州赛区 G题,生成函数 + 容斥 + 分治NTT)的更多相关文章

  1. HDU - 6513 Reverse It (SYSU校赛C题)(组合数学+容斥)

    题目链接 题意:给定一个n*m的矩阵,可以选择至多两个子矩阵将其反转,求能形成多少种不同的矩阵. 任选一个矩阵有$C_{n+1}^{2}C_{m+1}^{2}$种方法,任选两个不同的矩阵有$C_{C_ ...

  2. HDU 6271 Master of Connected Component(2017 CCPC 杭州 H题,树分块 + 并查集的撤销)

    题目链接  2017 CCPC Hangzhou Problem H 思路:对树进行分块.把第一棵树分成$\sqrt{n}$块,第二棵树也分成$\sqrt{n}$块.    分块的时候满足每个块是一个 ...

  3. HDU 6268 Master of Subgraph (2017 CCPC 杭州 E题,树分治 + 树上背包)

    题目链接  2017 CCPC Hangzhou  Problem E 题意  给定一棵树,每个点有一个权值,现在我们可以选一些连通的点,并且把这点选出来的点的权值相加,得到一个和. 求$[1, m] ...

  4. HDU 6240 Server(2017 CCPC哈尔滨站 K题,01分数规划 + 树状数组优化DP)

    题目链接  2017 CCPC Harbin Problem K 题意  给定若干物品,每个物品可以覆盖一个区间.现在要覆盖区间$[1, t]$. 求选出来的物品的$\frac{∑a_{i}}{∑b_ ...

  5. 2017 CCPC 杭州 流水账

    day0: 队内训练ccpc 秦皇岛,敝校自己出的题,感觉一个星期没怎么写代码,手生得很,不出意料被打飞了. day1 (热身赛): 热身赛还算顺利,A题看有的队几分钟就草过去了,还以为又是西安ICP ...

  6. HDU 4778 Gems Fight! (2013杭州赛区1009题,状态压缩,博弈)

    Gems Fight! Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 327680/327680 K (Java/Others)T ...

  7. HDU 4771 Stealing Harry Potter's Precious (2013杭州赛区1002题,bfs,状态压缩)

    Stealing Harry Potter's Precious Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  8. HDU 4770 Lights Against Dudely (2013杭州赛区1001题,暴力枚举)

    Lights Against Dudely Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  9. 2017 CCPC 杭州 HDU6265B 积性函数

    题目链接 http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf B题 数论题      h(n)=∑ d|n φ(d) × ...

随机推荐

  1. 斐波那契数列(Fibonacci) iOS

    斐波那契数列Fibonacci 斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2 ...

  2. 《数据结构与算法分析:C语言描述》复习——第六章“排序”——冒泡排序

    2014.06.17 01:04 简介: 冒泡排序是O(n^2)级别的交换排序算法,原理简单,属于必知必会的基础算法之一. 思路: 排序要进行N轮,每一轮从尾部逐个向前扫描,遇到逆序对就进行交换.确保 ...

  3. HDU 2295 Radar (二分 + Dancing Links 重复覆盖模型 )

    以下转自 这里 : 最小支配集问题:二分枚举最小距离,判断可行性.可行性即重复覆盖模型,DLX解之. A*的启发函数: 对当前矩阵来说,选择一个未被控制的列,很明显该列最少需要1个行来控制,所以ans ...

  4. CodeForces A. Many Equal Substrings

    http://codeforces.com/contest/1029/problem/A You are given a string tt consisting of nn lowercase La ...

  5. HTTPS和HTTP的区别:

    https协议需要到ca申请证书,一般免费证书很少,需要交费.http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议http和https使用的是完全不同的连接方式用的 ...

  6. 使用awk根据多维度统计系统tps

    业务简单日志格式: [2017-08-28 01:00:00.523]transfer_search,7001045,1708271100083774377,20170827,,,,,,,,,,001 ...

  7. 基于MAC OS 操作系统安装、配置hadoop

    在Mac上安装Hadoop 对我这个之前从未接触过*nix的用户来说,使用命令行来做一系列的事情还是废了一番功夫.特写这个记录,以做备份. 获取Java 我的Mac运行的操作系统是OS X 10.7 ...

  8. npm & npm config

    npm command show npm config https://docs.npmjs.com/cli/config https://docs.npmjs.com/cli/ls https:// ...

  9. HDU - 2814 Visible Trees

    题意: m*n(1<=m,n<=100000)的森林里,起始点在(1,1),某人从(0,0)点开始看,问能看到多少棵树. 题解: 求出1~x中的每个数与1~y的数中互质的数的总和.用素数筛 ...

  10. 实时流处理Storm、Spark Streaming、Samza、Flink孰优孰劣

    对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在不断的升级改进,从0.8.x版本开始到现在的1.1.x版本,Kafka的 ...