60pts:

每个DAG的拓扑序是唯一的,所以考虑将DAG分层。f[i][j]记录当前选择的节点状态是i,最后一层的节点状态为j(dep取最大)。

初始状态:$f[i][i]=1;i\in [1,1<<n)$。那么我们第一层枚举当前状态i,第二层枚举[1,1<<n)。那么令s=i&j,t=j&(~i),s即为i的一个子集,所以令s为当前的最后一层,t为i

的补集的一个子集,令t为转移后的最后一层,要求s到t中每个点都有边。枚举t中每个点,设ch1为集合$i-s$当前点的边数,ch2为s集合到当前点的边数,转移方程:$f[i$|$t][t]+=f[i][s]*\prod 2^{ch1}*\prod (2^{ch2}-1)$;

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<bitset>
#include<vector>
#define LL long long
using namespace std;
const int mod=1e9+;
struct edge
{
int u,v,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define n(x) ed[x].nxt
}ed[];
int first[],num_e;
#define f(x) first[x]
int n,m,ru[];
LL f[<<][<<];
vector<int> fr[];
bool pd(int s,int t)
{
bool ok=;
for(int i=;i<=n;i++)
if((<<i-)&t)
{
bool pd2=;
for(int j=;j<fr[i].size();j++)
if((<<fr[i][j]-)&s)pd2=;
ok&=pd2;
}
return ok;
}
LL find(int s,int po)
{
int res=;
for(int i=;i<fr[po].size();i++)
if((<<fr[po][i]-)&s)res++;
return res;
}
LL poww(LL a,int b);
inline void add(int u,int v);
signed main()
{
cin>>n>>m;int tu,tv;
for(int i=;i<=m;i++)cin>>tu>>tv,add(tu,tv),ru[tv]++,fr[tv].push_back(tu); for(int i=;i<(<<n);i++)f[i][i]=;
for(int i=;i<(<<n);i++)
{
for(int j=;j<(<<n);j++)
{
int s=i&j,t=j&(~i);
bitset<>t1(i),t2(s),t3(t);
// cout<<t1<<" "<<t2<<" "<<(t1|t3)<<" "<<t3<<endl;
if(s&&t&&pd(s,t))
{
int ch1=,ch2=;
for(int k=;k<=n;k++)
if((<<k-)&t)
{
int cnt1=find(i&(~s),k),cnt2=find(s,k);
ch1=ch1*poww(,cnt1)%mod;ch2=ch2*(poww(,cnt2)-)%mod;
}
f[i|t][t]=((f[i|t][t]+f[i][s]*ch1*ch2)%mod)%mod;
}
// cout<<f[i][s]<<" -> "<<f[i|t][t]<<endl;
}
}
LL ans=;
// for(int i=1;i<(1<<n);i++)
for(int j=;j<(<<n);j++)
ans=(ans+f[(<<n)-][j])%mod;
printf("%lld\n",ans);
}
inline void add(int u,int v)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
n(num_e)=f(u);
f(u)=num_e;
}
LL poww(LL a,int b)
{
LL ans=;
while(b)
{
if(b&)ans=ans*a%mod;
a=a*a%mod;b=b>>;
}
return ans;
}

100pts:

考虑将第二维去掉,f[i]表示当前集合为i时的方案数,那么$f[i]=\sum f[i][j]$,如果不记录最后一层的话,每一个j都会被计算进去多次,所以容斥一下就可以了(稍不明白)。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<bitset>
#include<vector>
#define re register
#define co const
#define rec re co
#define LL long long
using namespace std;
const int mod=1e9+;
struct edge
{
int u,v,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define n(x) ed[x].nxt
}ed[];
int first[],num_e;
#define f(x) first[x]
int n,m,ru[];
LL f[<<],g[<<];
int tem[<<][];
vector<int> fr[];
bool pd(int s,int t)
{
bool ok=;
for(int i=;i<=n;i++)
if((<<i-)&t)
{
bool pd2=;
for(int j=;j<fr[i].size();j++)
if((<<fr[i][j]-)&s)pd2=;
ok&=pd2;
}
return ok;
}
LL find(rec int s,rec int po)
{
int res=;
for(int i=;i<fr[po].size();i++)
if((<<fr[po][i]-)&s)res++;
return res;
}
int pw[];
int siz[<<];
LL poww(LL a,int b);
inline void add(rec int u,rec int v);
signed main()
{
// freopen("obelisk9.in","r",stdin); cin>>n>>m;int tu,tv;
for(re int i=;i<=m;i++)scanf("%d%d",&tu,&tv),add(tu,tv),ru[tv]++,fr[tv].push_back(tu); for(re int i=;i<(<<n);i++){bitset<>t(i);siz[i]=t.count();}
for(re int i=;i<(<<n);i++)for(re int j=;j<=n;j++)tem[i][j]=find(i,j);
f[]=;
pw[]=;for(int i=;i<=;i++)pw[i]=pw[i-]*%mod;
for(int i=;i<=n;i++)g[<<i-]=i;
int tttttt=(<<n);
for(re int i=;i<tttttt;i++)
{
int all=(~i)&(tttttt-);
for(re int k=all;k;k=(k-)&all)
{
int cnt=;
for(re int j=k;j;j-=(j&-j))
cnt+=tem[i][g[j&-j]]; if(siz[k]&)f[i|k]=(f[i|k]+f[i]*pw[cnt]%mod);
else f[i|k]=(f[i|k]-f[i]*pw[cnt]%mod);
if(f[i|k]<)f[i|k]=f[i|k]%mod+mod;
if(f[i|k]>=mod)f[i|k]-=mod;
}
} printf("%lld\n",(f[(<<n)-]%mod+mod)%mod);
}
inline void add(rec int u,rec int v)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
n(num_e)=f(u);
f(u)=num_e;
}
LL poww(LL a,int b)
{
LL ans=;
while(b)
{
if(b&)ans=ans*a%mod;
a=a*a%mod;b=b>>;
}
return ans;
}

HZOJ 巨神兵的更多相关文章

  1. BZOJ 3812 主旋律 (状压DP+容斥) + NOIP模拟赛 巨神兵(obelisk)(状压DP)

    这道题跟另一道题很像,先看看那道题吧 巨神兵(obelisk) 题面 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张nnn个点mmm条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张 ...

  2. [CSP-S模拟测试]:巨神兵(状压DP)

    题目描述 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张$n$个点$m$条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张图有多少个子图(即选定一个边集)是优美的?答案对$1,000 ...

  3. csp-s模拟测试57(10.2)「天空龙」·「巨神兵」·「太阳神」

    题目是古埃及神话??? A. 天空龙 傻逼模拟,看来没有滑天下之大稽QAQ,也没有打错快读(大雾...) B. 巨神兵 难度爆增,一脸懵比..... 60分状压: 因为是求有向图,关于有向图好像拓扑用 ...

  4. hzoj 2301(莫比乌斯反演)

    题意 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公 数. 思路: 与先前的那个相比,这次a,c并不一定 ...

  5. NOIp模拟赛 巨神兵(状压DP 容斥)

    \(Description\) 给定\(n\)个点\(m\)条边的有向图,求有多少个边集的子集,构成的图没有环. \(n\leq17\). \(Solution\) 问题也等价于,用不同的边集构造DA ...

  6. 【2016NOIP十连测】【test4】【状压DP】【容斥原理】巨神兵

    题目大意: 给一个n个点(n<=17),m条边的有向图(无自环.无重边),求其无环子图的方案数. 题解: 看到n<=17,显然是用状压dp. 用f[i]表示点集i的满足条件的方案数. 状态 ...

  7. HZOJ 单

    两个子任务真的是坑……考试的时候想到了60分的算法,然而只拿到了20分(各种沙雕错,没救了……). 算法1: 对于测试点1,直接n遍dfs即可求出答案,复杂度O(n^2),然而还是有好多同学跑LCA/ ...

  8. 20191102 「HZOJ NOIP2019 Round #12」20191102模拟

    先开坑. md原题写挂我也真是... 100+20+10 白夜 打表大法吼 显然,不在环上的点对答案的贡献是 \((k-cycle)^{k-1}\) . 打表得到环上的递推式,矩阵一下乘起来就好了. ...

  9. 20191004 「HZOJ NOIP2019 Round #9」20191004模拟

    综述 第一次 rk1 ,激动. 题目是 COCI 18/19 Round #1 的三至五题. 得分 \(100+100+20\) \(\mathrm{cipele}\) 问题描述 HZOJ1313 题 ...

随机推荐

  1. uwsgi: invalid option -- 'x'

    安装:pip install uwsgi 启动:uwsgi -x 'uwsgi.xml'报错:uwsgi: invalid option -- 'x' 原因:centos下,在没有安装libxml2时 ...

  2. mac ssh 远程容易断线解决方案

    编辑文件 /etc/ssh/ssh_config 添加下面两行 ServerAliveInterval 60 ServerAliveCountMax 3 说明一下: #server每隔60秒发送一次请 ...

  3. ACMer之歌

    <<死了都要编>> 死了都要编 不动态规划不痛快 算法多深只有这样 才足够表白 死了都要编 不A星算法不痛快 宇宙毁灭星还在 把每天当成是比赛来编程 一分一秒都编到汗水掉下来 ...

  4. Zigbee安全入门(一)—— 技术介绍和安全策略

    么是Zigbee? Zigbee说白了就是类似wifi.蓝牙的一种交换数据的方式,学术点说就是低成本.用于低功耗嵌入式设备(无线电系统),用以促进机器与机器之间高效且有效通信(通常相距10-100米) ...

  5. 蛋疼的JavaScript(二)this

    ### 烦人的this JavaScript的表现与之前学的任何传统的语言都不一样,这个就很烦人,这几天把这个坑扫除了 ### this到底指向什么 总的来说,总结下,this其实取决于调用者的上下文 ...

  6. 2019.9.20 csp-s模拟测试48 反思总结

    头疼,不说废话了,祝大家rp++. T1: 暴力枚举,n3. 枚举两个串开始匹配的位置,每一次尽量修改. #include<iostream> #include<cstdio> ...

  7. 洛谷P1164 小A点菜 [2017年4月计划 动态规划08]

    P1164 小A点菜 题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过u ...

  8. DOM 创建元素 删除元素(结点)

    创建新的 HTML 元素 如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素. <script> var para=document. ...

  9. NOIP模拟 7.05

    Problem 1 双色球(ball.cpp/c/pas) [题目描述] 机房来了新一届的学弟学妹,邪恶的chenzeyu97发现一位学弟与他同名,于是他当起了善良的学长233 “来来来,学弟,我考你 ...

  10. Leetcode849.Maximize Distance to Closest Person到最近的人的最大距离

    在一排座位( seats)中,1 代表有人坐在座位上,0 代表座位上是空的. 至少有一个空座位,且至少有一人坐在座位上. 亚历克斯希望坐在一个能够使他与离他最近的人之间的距离达到最大化的座位上. 返回 ...