LOJ #6358 前夕 (组合计数、容斥原理)
题目链接
https://loj.ac/problem/6358
(另外一道\(4\)的倍数题左转loj #6356)
题意
题面写得就像一坨X一样,我来复述一下吧。
有\(N\)个元素构成的集合,要从\(2^N\)个子集中选出若干个使得交的大小为\(4\)的倍数。不选算交为空。
样例解释: 选空集有\(8\)种方案,不选空集方案只有\(\{ 1\} \{ 2\}\)和\(\{ 1\} \{ 2\} \{1,2\}\), 还有一种什么都不选,共\(11\)种。
题解
这道题真的神仙得令我目瞪口呆。。
首先考虑一个简单的容斥: 令\(F(k)\)表示钦定\(k\)个元素在所有选出的子集中必须出现,则\(F(k)={N\choose k}(2^{2^{N-k}}-1)\).
令\(G(k)\)表示交集恰好为\(k\)的方案数,则有\(F(k)=\sum^{N}_{i=k} {i\choose k}G(i), G(k)=\sum^{N}_{i=k} (-1)^{i-k}{i\choose k}F(i)\).
那么要求的就是\(ans=\sum^N_{k\equiv 0(\mod 4)} G(k)\).
前方高能——
我们考虑构造一个系数\(\alpha(i)\) (官方题解将它称为“容斥系数” ) 使得\(ans=\sum^{N}_{i=0}F(i)\alpha(i)\).
如果没有\(k\)是\(4\)的倍数这个条件,对所有\(k\)求和,那么根据容斥的式子可以推出来\(\alpha(i)=[i=0]\)即可达到目的。
现在有了这个条件,我们考虑刚才实际上我们在干什么:
对于一个\(G(n)\), 其在\(F(k)\)中会被计算\(n\choose k\)次,我们希望总共计算的次数是\(1\)次,那么也就是$$\forall n, \sum^{n}_{k=0} {n\choose k}\alpha(k)=1$$, 取\(\alpha(k)=[k=0]\)即可. 现在我们就是要\(\forall n, \sum^{n}_{k=0} {n\choose k}\alpha(k)=[k\equiv 0(\mod 4)]\). 于是根据二项式反演有\(\alpha(n)=\sum^{n}_{k=0} (-1)^{n-k}{n\choose k}[k\equiv 0(\mod 4)]\).
这个东西怎么快速求?掏出数论中走街串巷杀题越货之必备良品——单位根!令\(m=4\), \(\omega\)为\(4\)次(主)单位根,则有$$[n\equiv 0(\mod m)]=\frac{1}{m}\sum^{m-1}_{i=0} \omega^{in}$$
于是\(\alpha(n)=\frac{1}{m}\sum^{n}_{k=0}(-1)^{n-k}{n\choose k}\sum^{m-1}_{i=0}(\omega^i)^k=\frac{1}{m}\sum^{m-1}_{i=0}(\omega^i-1)^n\)
直接计算即可。
时间复杂度\(O(Nm)\).
启示: 最近连做了两道神仙构造的题,经常可以构造一些转移矩阵/容斥系数/递推式之类的东西以达到目的,这种思路值得借鉴。
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#define llong long long
using namespace std;
inline int read()
{
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x;
return -x;
}
const int N = 1e7;
const int P = 998244353;
const llong G = 3ll;
const llong W = 911660635ll;
const llong INV4 = 748683265ll;
int fact[N+3],finv[N+3];
llong f[N+3],a[N+3];
int n;
llong quickpow(llong x,llong y)
{
llong cur = x,ret = 1ll;
for(int i=0; y; i++)
{
if(y&(1ll<<i)) {y-=(1ll<<i); ret = ret*cur%P;}
cur = cur*cur%P;
}
return ret;
}
llong comb(llong x,llong y) {return x<0||y<0||x<y ? 0ll : (llong)fact[x]*(llong)finv[y]%P*(llong)finv[x-y]%P;}
int main()
{
fact[0] = 1ll; for(int i=1; i<=N; i++) fact[i] = (llong)fact[i-1]*i%P;
finv[N] = quickpow(fact[N],P-2); for(int i=N-1; i>=0; i--) finv[i] = (llong)finv[i+1]*(i+1ll)%P;
scanf("%d",&n);
f[n] = 2ll; for(int i=n-1; i>=0; i--) f[i] = f[i+1]*f[i+1]%P;
for(int i=0; i<=n; i++) f[i]--;
for(int i=0; i<=n; i++) f[i] = f[i]*comb(n,i)%P;
for(int i=0; i<4; i++)
{
llong tmp = 1ll,expn = quickpow(W,i);
for(int j=0; j<=n; j++)
{
a[j] = (a[j]+tmp)%P;
tmp = tmp*(expn-1ll)%P;
}
}
for(int i=0; i<=n; i++) a[i] = a[i]*INV4%P;
// for(int i=0; i<=n; i++) printf("%lld ",a[i]); puts("");
llong ans = 1ll;
for(int i=0; i<=n; i++) ans = (ans+f[i]*a[i])%P;
printf("%lld\n",ans);
return 0;
}
LOJ #6358 前夕 (组合计数、容斥原理)的更多相关文章
- 集训队8月9日(组合计数+容斥原理+Mobius函数)
刷题数:4 今天看了组合计数+容斥原理+Mobius函数,算法竞赛进阶指南169~179页 组合计数 https://www.cnblogs.com/2462478392Lee/p/11328938. ...
- BZOJ 4555: [Tjoi2016&Heoi2016]求和 [FFT 组合计数 容斥原理]
4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...
- bzoj2839 集合计数 组合计数 容斥原理|题解
集合计数 题目描述 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使得它们的交集的元素个数为K,求取法的方案数,答案模1000000007.(是 ...
- UVa 11806 - Cheerleaders (组合计数+容斥原理)
<训练指南>p.108 #include <cstdio> #include <cstring> #include <cstdlib> using na ...
- BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]
4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...
- [总结]数论和组合计数类数学相关(定理&证明&板子)
0 写在前面 0.0 前言 由于我太菜了,导致一些东西一学就忘,特开此文来记录下最让我头痛的数学相关问题. 一些引用的文字都注释了原文链接,若侵犯了您的权益,敬请告知:若文章中出现错误,也烦请告知. ...
- ACM组合计数入门
1 排列组合 1.1 排列 \[A_n^m=n(n-1)(n-2)\cdots(n-m+1)=\frac{n!}{(n-m)!} \] 定义:从 n 个中选择 m 个组成有序数列,其中不同数列的数量. ...
- bzoj 2281 [Sdoi2011]黑白棋(博弈+组合计数)
黑白棋(game) [问题描述] 小A和小B又想到了一个新的游戏. 这个游戏是在一个1*n的棋盘上进行的,棋盘上有k个棋子,一半是黑色,一半是白色. 最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色 ...
- 【BZOJ5491】[HNOI2019]多边形(模拟,组合计数)
[HNOI2019]多边形(模拟,组合计数) 题面 洛谷 题解 突然特别想骂人,本来我考场现切了的,结果WA了几个点,刚刚拿代码一看有个地方忘记取模了. 首先发现终止态一定是所有点都向\(n\)连边( ...
随机推荐
- Java 类的构造器中this()和super()的困惑
关于构造器中super的使用,书本上这样写: “super是指向父类的引用,如果构造方法没有显示地调用父类的构造方法,那么编译器会自动为它加上一个默认的super()方法调用.如果父类由没有默认的无参 ...
- 10 Scrapy框架持久化存储
一.基于终端指令的持久化存储 保证parse方法中有可迭代类型对象(通常为列表or字典)的返回,该返回值可以通过终端指令的形式写入指定格式的文件中进行持久化操作. 执行输出指定格式进行存储:将爬取到的 ...
- mysql explain解析一 extra中的using index,using where,using index condition
1.简单介绍 using index 和using where只要使用了索引我们基本都能经常看到,而using index condition则是在mysql5.6后新加的新特性,我们先来看看mysq ...
- 树莓派wifi环境下初始化及环境配置
在此放一下我的系统 链接:https://pan.baidu.com/s/192cL6qSsMd-wqxHeDWfIug 提取码:0lrq 1.准备一张内存卡,最好是32G class10 16G的话 ...
- JVM内存区域划分总结
发现网上有两个版本的JVM内存划分,一个是按照<深入理解JVM虚拟机>上的版本,包含程序计数器等,按照是否线程共享划分. 另一个我觉得更好记一些,也更适合我自己,在这里记录一下. 首先上思 ...
- 韦东山嵌入式Linux学习笔记02--如何给开发板烧录程序
购买韦东山嵌入式开发板jz2440 v3会标配两根usb线和一根网线,OpenJtag需要单独购买, 我暂时还没买到该工具. 下面介绍usb烧录以及通过网线烧录程序. 1.usb烧录程序: 借助DNW ...
- 初识linux内核漏洞利用
0x00 简介 之前只接触过应用层的漏洞利用, 这次第一次接触到内核层次的,小结一下. 0x01 概况 这次接触到的,是吾爱破解挑战赛里的一个题,给了一个有问题的驱动程序,要求在ubuntu 14.0 ...
- python动态添加属性
class A: def __init__(self, info ={}): self.info = info def __getattr__(self, item): return self.inf ...
- OpenCV 在VS2013的安装
现在就介绍下如何在VS2013上配置openCV3.0的方法 如果是32位操作系统的:https://www.cnblogs.com/ssjie/p/4943439.html 1.下载openCV3. ...
- zencart批量设置热卖商品 best seller、点击最高最受欢迎产品 most popular
zencart批量设置某分类下热卖商品数 best seller ; ,,,,,); zencart批量设置某产品点击最高最受欢迎产品 most popular ; ,,,,,);