[hdu 6355] Fireflies
题意
在一个\(n\)维有限超立方体\(((1, p_1), (1, p_2), ... , (1, p_n))\)中,你可以在若干个位置放一只萤火虫。
萤火虫可以行动若干次,每一次从\((x_1, x_2, x_3,...,x_n)\)走向\((y_1, y_2, y_3,...,y_n)\),都要满足:
1.起点和终点要在超立方体内;
2.\(\forall_i x_i \le y_i\);
3.\((\sum y_i - x_i) = 1\)。
求最开始最少放多少个,才能确保存在一种方案,对于每一个单位空间,至少用一只萤火虫遍历它。
题解
最优解的结构可以用Dilworth定理来分析。
Dilworth定理表明,最小链覆盖数等于最大反链数,也即选出一个集合,使得集合中的位置两两不可达,要最大化这个集合的大小。
Sperner定理表明,若要选择一个集合\(S\)的幂集的一个子集使得其中没有一个集合包含在另一个集合中,则这种子集的大小最大为\(\binom {|S|}{\lfloor |S| / 2 \rfloor}\)。
则Sperner定理的一个推广)恰好能给出本问题的解:
选择\(n\)维坐标之和为\(M = \lfloor \frac {1}{2} \sum_{i = 1} ^ n (p_i + 1) \rfloor\)的位置即可达到最大的数量。
则现在问题转化为求\(\sum_{i = 1} ^ n x_i = M\)且\(1 \le x_i \le p_i\)的解的数量。
这是个经典问题,可以用容斥来做。
但考虑到\(n \le 32\),不能直接容斥。
容易想到可能会用到meet-in-middle。但是如何用中途相遇法呢?
考虑到如果我们容斥时选出集合\(S\)代表\(S\)中的\(x_i\)都至少比\(p_i\)大,方案数就是
\[ \max(0, \binom{M - 1 - \sum_{i \in S} p_i}{n - 1}) \]
考虑到\(n\)很小,然后就有一个套路,将这个组合数看成下降幂形式,然后就成了\(\sum_{i \in S} p_i\)的\(n - 1\)次多项式。那么我们可以先预处理出这个多项式的系数,然后在处理出每个集合\(S\)的\(\sum_{i \in S} p_i\)(这里的\(S\)是折半枚举的),然后meet-in-middle的时候合并一下,用个前缀和优化就好了。
注意到如果\(M - 1 - \sum_{i \in S}p_i < 0\),不能用下降幂来算,这种情况方案数应该算作\(0\)(实际上在这个问题中\(\binom {n}{m}\)只要\(n < m\)就是\(0\))。处理时,可以用一个双指针来搞一搞这部分。
最终复杂度大概是\(O(2 ^ {n / 2} n ^ 2)\)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;const int N = 40, mo = 1e9 + 7;
const int M = 1 << 16 | 5;
inline int read () {static int x;scanf("%d", &x);return x;
}
inline ll exp (ll a, ll b, ll ret = 1) {for (a %= mo; b; b >>= 1, a = a * a % mo)if (b & 1) ret = ret * a % mo;return ret;
}int n, m, a[N];
int bitcnt[M];
ll k, cb[N][N], ivf[N];
ll f[N][N], coe[N];void prework () {ivf[0] = 1;for (int i = 1; i < N; ++i)ivf[i] = ivf[i - 1] * exp(i, mo - 2) % mo;bitcnt[0] = 0;for (int i = 1; i < M; ++i)bitcnt[i] = bitcnt[i >> 1] + (i & 1);cb[0][0] = 1;for (int i = 1; i < N; ++i) {cb[i][0] = cb[i][i] = 1;for (int j = 1; j < i; ++j)cb[i][j] = (cb[i - 1][j - 1] + cb[i - 1][j]) % mo;}
}
void predo () {memset(f, 0, sizeof f);f[0][0] = n & 1 ? 1 : -1;for (int i = 1; i < n; ++i) {for (int j = 1; j < n; ++j)f[i][j] = f[i - 1][j - 1];for (int j = 0; j < n; ++j)f[i][j] = (f[i][j] - f[i - 1][j] * ((k - i) % mo) % mo + mo) % mo;}for (int i = 0; i < n; ++i)coe[i] = f[n - 1][i] * ivf[n - 1] % mo;
}pair <ll, vector <ll> > p[M], q[M];
ll presum[N];
ll in_ex (ll ret = 0) {for (int s = 0; s < (1 << m); ++s) {ll sum = 0; int sgn = bitcnt[s] & 1 ? -1 : 1;for (int i = 0; i < m; ++i)if (s >> i & 1) sum += a[i];p[s].first = sum, p[s].second.resize(n, 0);for (int i = 0; i < n; ++i)p[s].second[i] = exp(sum % mo, i) * sgn % mo;}sort(p, p + (1 << m));for (int s = 0; s < (1 << (n - m)); ++s) {ll sum = 0; int sgn = bitcnt[s] & 1 ? -1 : 1;for (int i = 0; i < (n - m); ++i)if (s >> i & 1) sum += a[i + m];q[s].first = sum, q[s].second.resize(n, 0);for (int i = 0; i < n; ++i)q[s].second[i] = exp(sum % mo, i) * sgn % mo;}sort(q, q + (1 << (n - m)));memset(presum, 0, sizeof presum);for (int s = (1 << m) - 1, t = 0; ~s; --s) {for ( ; t < (1 << (n - m)) && k - n - (p[s].first + q[t].first) >= 0; ++t) {for (int i = 0; i < n; ++i) presum[i] = (presum[i] + q[t].second[i]) % mo;}for (int i = 0; i < n; ++i) {ll tmp = 0;for (int j = 0; j <= i; ++j)tmp = (tmp + cb[i][j] * p[s].second[j] % mo * presum[i - j] % mo) % mo;ret = (ret + coe[i] * tmp) % mo;}}return (ret % mo + mo) % mo;
}
signed main () {prework();for (int _ = read(); _; --_) {n = read(), m = (n + 1) / 2, k = 0;for (int i = 0; i < n; ++i)a[i] = read(), k += a[i] + 1;k /= 2;if (n == 1) {printf("1\n");continue;}predo();printf("%lld\n", in_ex());}return 0;
}
转载于:https://www.cnblogs.com/psimonw/p/10727408.html
[hdu 6355] Fireflies相关推荐
- HDU 4389 - X mod f(x)
题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4389 2012多校,第9场,1010 . 问题是,询问区间内 存在多少个 哈沙德数(Harshad ...
- hdu 4389 囧,打表
http://acm.hdu.edu.cn/showproblem.php?pid=4389 题意 :一个数能被他各个位数之和整除则符合要求,给L,R,问区间里有多少个数符合要求. 囧,居然打表就能过 ...
- HDU——1106排序(istringstream的使用、STLvector练习)
排序 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...
- hdu 5438 Ponds 拓扑排序
Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem ...
- HDU 1248 寒冰王座(全然背包:入门题)
HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid=1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票 ...
- hdu 1312 Red and Black 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 第二条深搜,题目并不难,但是做了我好久好久,由于一个细节,让我赌上了一个晚上的时间. 题目大意: ...
- HDU 1429 胜利大逃亡(续) (BFS+位压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others) ...
- hdu 1272 小希的迷宫
Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该 ...
- HDOJ 1157 HDU 1157 Who's in the Middle ACM 1157 IN HDU
MiYu原创, 转帖请注明 : 转载自 ______________白白の屋 题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1157 题目描述: ...
最新文章
- PaddlePaddle推理部署
- 如何在 Linux 上永久挂载一个 Windows 共享
- B站up主硬核打造「螃蟹火星车」,遥控、拍照、测距,还能做人脸检测;网友:赛博螃克...
- cs6 数据库mysql_能mysql内容
- redis 启动时 Warning 警告解决及说明
- 进程、线程、协程对比
- Python读写与追加excel文件
- linux 学习笔记 -vim 操作
- Java 安全套接字编程以及keytool 使用最佳实践
- 论文阅读——Don‘t Stop Pretraining: Adapt Language Models to Domains and Tasks
- 一群在全球顶会崭露头角的阿里新生代白帽:能查漏洞还会焊接
- 【易通慧谷】通过一个案例两张概念图解析供应链金融
- 使用quartz 定时任务
- Android Tech Weekly - 45 :再不好好学习,Copilot 就取代你了
- 雷达威力计算 matlab,威力雷达指标
- 使用python快速查看hdf5文件
- Linux 系统 CPU 占用率较高问题排查思路
- java工作中最有成就感的事_工作中最有成就感的事
- GNSS定位精度指标计算
- iOS---学习研究大牛Git高星项目YYCategories(二)