题意

在一个\(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相关推荐

  1. HDU 4389 - X mod f(x)

    题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4389 2012多校,第9场,1010 . 问题是,询问区间内 存在多少个 哈沙德数(Harshad ...

  2. hdu 4389 囧,打表

    http://acm.hdu.edu.cn/showproblem.php?pid=4389 题意 :一个数能被他各个位数之和整除则符合要求,给L,R,问区间里有多少个数符合要求. 囧,居然打表就能过 ...

  3. HDU——1106排序(istringstream的使用、STLvector练习)

    排序 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  4. hdu 5438 Ponds 拓扑排序

    Ponds Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/contests/contest_showproblem ...

  5. HDU 1248 寒冰王座(全然背包:入门题)

    HDU 1248 寒冰王座(全然背包:入门题) http://acm.hdu.edu.cn/showproblem.php?pid=1248 题意: 不死族的巫妖王发工资拉,死亡骑士拿到一张N元的钞票 ...

  6. hdu 1312 Red and Black 解题报告

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 第二条深搜,题目并不难,但是做了我好久好久,由于一个细节,让我赌上了一个晚上的时间. 题目大意: ...

  7. HDU 1429 胜利大逃亡(续) (BFS+位压缩)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1429 胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)  ...

  8. hdu 1272 小希的迷宫

    Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该 ...

  9. HDOJ 1157 HDU 1157 Who's in the Middle ACM 1157 IN HDU

    MiYu原创, 转帖请注明 : 转载自 ______________白白の屋   题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1157 题目描述: ...

最新文章

  1. PaddlePaddle推理部署
  2. 如何在 Linux 上永久挂载一个 Windows 共享
  3. B站up主硬核打造「螃蟹火星车」,遥控、拍照、测距,还能做人脸检测;网友:赛博螃克...
  4. cs6 数据库mysql_能mysql内容
  5. redis 启动时 Warning 警告解决及说明
  6. 进程、线程、协程对比
  7. Python读写与追加excel文件
  8. linux 学习笔记 -vim 操作
  9. Java 安全套接字编程以及keytool 使用最佳实践
  10. 论文阅读——Don‘t Stop Pretraining: Adapt Language Models to Domains and Tasks
  11. 一群在全球顶会崭露头角的阿里新生代白帽:能查漏洞还会焊接
  12. 【易通慧谷】通过一个案例两张概念图解析供应链金融
  13. 使用quartz 定时任务
  14. Android Tech Weekly - 45 :再不好好学习,Copilot 就取代你了
  15. 雷达威力计算 matlab,威力雷达指标
  16. 使用python快速查看hdf5文件
  17. Linux 系统 CPU 占用率较高问题排查思路
  18. java工作中最有成就感的事_工作中最有成就感的事
  19. GNSS定位精度指标计算
  20. iOS---学习研究大牛Git高星项目YYCategories(二)

热门文章

  1. 局域网计算机配置扫描系统,fly42局域网计算机配置检测系统
  2. 基于BAS算法实现复杂网络社区发现问题——附python代码
  3. 达内培训python 好不好
  4. 英语不好能学python吗_英语和数学不好的人能学会Python编程吗?
  5. 算法中的最优化方法总结(中国科学院大学)
  6. Elastic 许可更新
  7. 【转载】浮华背后与我的路
  8. PEEL——深度隐写信息去除攻击——PEEL: A Provable Removal Attack on Deep Hiding
  9. Scrapy爬取斗破苍穹漫画
  10. iOS开发之数据存储