[ZJOI2016]小星星&[SHOI2016]黑暗前的幻想乡(容斥)
这两道题思路比较像,所以把他们放到一块。
[ZJOI2016]小星星
题目描述
小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品。她有n颗小星星,用m条彩色的细线串了起来,每条细线连着两颗小星星。
有一天她发现,她的饰品被破坏了,很多细线都被拆掉了。这个饰品只剩下了n-1条细线,但通过这些细线,这颗小星星还是被串在一起,也就是这些小星星通过这些细线形成了树。小Y找到了这个饰品的设计图纸,她想知道现在饰品中的小星星对应着原来图纸上的哪些小星星。如果现在饰品中两颗小星星有细线相连,那么要求对应的小星星原来的图纸上也有细线相连。小Y想知道有多少种可能的对应方式。
只有你告诉了她正确的答案,她才会把小饰品做为礼物送给你呢。
题解
做容斥题有一个基本模型,就是有一个限制,我们直接在转移或者统计复杂度过高,但如果把它放宽一点的话复杂度会降低许多。
然后总的条件数也支持2^n枚举,就可以去考虑容斥。
这个题是说,有一个n个点的无向图和n个点的一棵树,问有多少种一一对应的映射使得在树中有的边,图中也有。
看到树可以联想树形dp,因为我们要求一一对应,所以我们可以考虑设dp[i][j][s]表示以i为根的子树,i对应了图中的j,i子树对应了图中的集合s的方案数。
转移还是比较简单的。
我们观察到这个算法复杂度瓶颈在于枚举s,所以我们考虑能不能去掉。
去掉之后会出现树中的多个点对应了图中的一个点,方案数会算多。
怎么办?这个形式其实已经很明显了,直接套用容斥公式算就好了。
2^n枚举图中选那些点,然后做二维的树形dp就好了。
代码
#include<iostream>
#include<cstdio>
#define N 18
#define R register
using namespace std;
typedef long long ll;
int n,m,tot,head[N],cou[<<N];
ll dp[N][N],ans;
bool a[N][N],jin[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to;}e[N*N*];
inline void add(int u,int v){
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;
}
void dfs(int u,int fa){
for(R int i=;i<=n;++i)if(!jin[i])dp[u][i]=;else dp[u][i]=;
for(R int i=head[u];i;i=e[i].n)if(e[i].to!=fa){
int v=e[i].to;dfs(v,u);
for(R int j=;j<=n;++j)if(!jin[j]){
ll num=;
for(R int k=;k<=n;++k)if(a[j][k]&&!jin[k])num+=dp[v][k];
dp[u][j]*=num;
}
}
}
int main(){
n=rd();m=rd();int x,y;
for(R int i=;i<=m;++i){
x=rd();y=rd();
a[x][y]=a[y][x]=;
}
for(R int i=;i<n;++i){x=rd();y=rd();add(x,y);add(y,x);}
for(R int i=;i<(<<n);++i){
cou[i]=cou[i>>]+(i&);
for(R int j=;j<=n;++j)jin[j]=(i&(<<j-))!=;
dfs(,);
ll num=;
for(R int j=;j<=n;++j)num+=dp[][j];
if(cou[i]&)ans-=num;else ans+=num;
}
cout<<ans;
return ;
}
[SHOI2016]黑暗前的幻想乡
题目描述
四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖怪涌入了幻想乡,扰乱了幻想乡昔日的秩序。但是幻想乡的建制派妖怪(人类)博丽灵梦和八云紫等人整日高谈所有妖怪平等,幻想乡多元化等等,对于幻想乡目前面临的种种大问题却给不出合理的解决方案。
风见幽香是幻想乡里少有的意识到了问题严重性的大妖怪。她这次勇敢地站了出来参加幻想乡大选,提出包括在幻想乡边境建墙(并让人类出钱),大力开展基础设施建设挽回失业率等一系列方案,成为了大选年出人意料的黑马并顺利地当上了幻想乡的大统领。
幽香上台以后,第一项措施就是要修建幻想乡的公路。幻想乡一共有 nn 个城市,之前原来没有任何路。幽香向选民承诺要减税,所以她打算只修 n-1n−1条公路将这些城市连接起来。但是幻想乡有正好 n-1n−1 个建筑公司,每个建筑公司都想在修路地过程中获得一些好处。虽然这些建筑公司在选举前没有给幽香钱,幽香还是打算和他们搞好关系,因为她还指望他们帮她建墙。所以她打算让每个建筑公司都负责一条路来修。
每个建筑公司都告诉了幽香自己有能力负责修建的路是哪些城市之间的。所以幽香打算 n - 1n−1条能够连接幻想乡所有城市的边,然后每条边都交给一个能够负责该边的建筑公司修建,并且每个建筑公司都恰好修建一条边。
幽香现在想要知道一共有多少种可能的方案呢?两个方案不同当且仅当它们要么修的边的集合不同,要么边的分配方式不同。
题解
这题和上一题相似,有两个限制。
上一题是要满足树中和图中都要有某条边。
这题是要满足我们的生成树中,既要有n个不同的点,还要满足每种颜色的边个出现一次。
如果我们去掉第二个限制,那就变成了生成树计数问题,套用矩阵树定理即可。
然后我们发现面前的这个问题还是可以套用容斥公式直接计算的,于是这道题被愉快的解决了。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#define N 18
using namespace std;
typedef long long ll;
const int mod=1e9+;
ll a[N][N];
int n,m,cou[<<N];
bool tag[N];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
inline ll power(ll x,ll y){
ll ans=;
while(y){if(y&)ans=ans*x%mod;x=x*x%mod;y>>=;}
return ans;
}
struct node{int x,y;};
vector<node>vec[N];
inline ll ni(ll x){return power(x,mod-);}
inline ll gauss(ll tot){
ll ans=;
for(int i=;i<=tot;++i)
for(int j=i+;j<=tot;++j){
ll t=a[j][i]*ni(a[i][i])%mod;
for(int k=i;k<=tot;++k)a[j][k]=((a[j][k]-t*a[i][k])%mod+mod)%mod;
}
for(int i=;i<=tot;++i)ans=(ans*a[i][i]%mod+mod)%mod;
return ans;
}
inline ll work(){
memset(a,,sizeof(a));
for(int i=;i<n;++i)if(tag[i]){
for(int j=;j<vec[i].size();++j){
int x=vec[i][j].x,y=vec[i][j].y;
a[x][x]++;a[y][y]++;a[x][y]--;a[y][x]--;
}
}
return gauss(n-);
}
int main(){
n=rd();int x,y;
for(int i=;i<n;++i){
m=rd();
for(int j=;j<=m;++j){
x=rd();y=rd();vec[i].push_back(node{x,y});
}
}
ll ans=;
for(int i=;i<(<<n-);++i){
cou[i]=cou[i>>]+(i&);
for(int j=;j<=n-;++j)tag[j]=(i&(<<j-))==;
if(cou[i]&)ans-=work();else ans+=work();
ans=(ans%mod+mod)%mod;
}
cout<<ans;
return ;
}
[ZJOI2016]小星星&[SHOI2016]黑暗前的幻想乡(容斥)的更多相关文章
- 【BZOJ4596】[Shoi2016]黑暗前的幻想乡 容斥+矩阵树定理
[BZOJ4596][Shoi2016]黑暗前的幻想乡 Description 幽香上台以后,第一项措施就是要修建幻想乡的公路.幻想乡有 N 个城市,之间原来没有任何路.幽香向选民承诺要减税,所以她打 ...
- BZOJ 4596: [Shoi2016]黑暗前的幻想乡(容斥+Matrix_Tree)
传送门 解题思路 看到计数想容斥--\(from\) \(shadowice1984\)大爷.首先求出原图的生成树个数比较容易,直接上矩阵树定理,但这样会多算一点东西,会把\(n-2\)个公司的多算进 ...
- 洛谷 P4336 黑暗前的幻想乡 —— 容斥+矩阵树定理
题目:https://www.luogu.org/problemnew/show/P4336 当作考试题了,然而没想出来,呵呵. 其实不是二分图完美匹配方案数,而是矩阵树定理+容斥... 就是先放上所 ...
- bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 559 Solved: 325[Submit][Sta ...
- bzoj4596[Shoi2016]黑暗前的幻想乡 Matrix定理+容斥原理
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 464 Solved: 264[Submit][Sta ...
- P4336 [SHOI2016]黑暗前的幻想乡
P4336 [SHOI2016]黑暗前的幻想乡 矩阵树定理(高斯消元+乘法逆元)+容斥 ans=总方案数 -(公司1未参加方案数 ∪ 公司2未参加方案数 ∪ 公司3未参加方案数 ∪ ...... ∪ ...
- 【BZOJ 4596】 4596: [Shoi2016]黑暗前的幻想乡 (容斥原理+矩阵树定理)
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 324 Solved: 187 Description ...
- bzoj4596/luoguP4336 [SHOI2016]黑暗前的幻想乡(矩阵树定理,容斥)
bzoj4596/luoguP4336 [SHOI2016]黑暗前的幻想乡(矩阵树定理,容斥) bzoj Luogu 题解时间 看一看数据范围,求生成树个数毫无疑问直接上矩阵树定理. 但是要求每条边都 ...
- BZOJ4596: [Shoi2016]黑暗前的幻想乡
Description 四年一度的幻想乡大选开始了,最近幻想乡最大的问题是很多来历不明的妖 怪涌入了幻想乡,扰乱了幻想乡昔日的秩序.但是幻想乡的建制派妖怪(人类) 博丽灵梦和八云紫等人整日高谈所有妖怪 ...
随机推荐
- 【学习总结】Master课程 之 虚拟化与云计算
Section 1- Cloud Computing Introduction-云计算介绍 1-What can Cloud Computing do? - 云计算可以做什么? 服务模式:美国国家标准 ...
- How To: Capture Android & iOS Traffic with Fiddler
How To: Capture iOS Traffic with Fiddlerhttps://www.telerik.com/blogs/how-to-capture-ios-traffic-wit ...
- CMMI摘要
CMMI_百度百科https://baike.baidu.com/item/CMMI CMMI分为哪几个等级?CMMI等级介绍_百度经验https://jingyan.baidu.com/articl ...
- React-Native之截图组件view-shot的介绍与使用
React-Native之截图组件view-shot的介绍与使用 一,需求分析 1,需要将分享页生成图片,并分享到微信好友与朋友圈. 二,react-native-view-shot介绍 1,可以截取 ...
- [转帖]SAP一句话入门:Finacial & Controlling Accounting
SAP一句话入门:Finacial & Controlling Accounting http://blog.vsharing.com/MilesForce/A621147.html 财务,财 ...
- [转帖]pfSense软路由系统的使用
图解pfSense软路由系统的使用(NAT功能) http://seanlook.com/2015/04/23/pfsense-usage/ 发表于 2015-04-23 | 更新于: 2015- ...
- [转帖]你云我云•兄弟夜谈会 第三季 企业IT架构
你云我云•兄弟夜谈会 第三季 企业IT架构 https://www.cnblogs.com/sammyliu/p/10425252.html 你云我云•兄弟夜谈会 第三季 企业IT架构 你云我云•兄弟 ...
- 初次启动hive,解决 ls: cannot access /home/hadoop/spark-2.2.0-bin-hadoop2.6/lib/spark-assembly-*.jar: No such file or directory问题
>>提君博客原创 http://www.cnblogs.com/tijun/ << 刚刚安装好hive,进行第一次启动 提君博客原创 [hadoop@ltt1 bin]$ ...
- linux audit审计(3)--audit服务配置
audit守护进程可以通过/etc/audit/auditd.conf文件进行配置,默认的auditd配置文件可以满足大多数环境的要求. local_events = yes write_logs = ...
- sqlmap-学习1 配置环境
sqlmap是一款非常强大的开源sql自动化注入工具,可以用来检测和利用sql注入漏洞.它由python语言开发而成,因此运行需要安装python环境 1 安装 python (https://www ...