AT2390-[AGC016F]Games on DAG【状压dp,SG函数】

1|0正题

题目链接:https://www.luogu.com.cn/problem/AT2390


1|1解题思路

n个点的DAGm条边可有可无,12上有石头。求有多少种方案使得先手必胜。

1n15,1mn(n1)2


1|2解题思路

这个复杂度比较麻烦,要设计一个比较巧妙的dp

考虑到题目是问多少种情况SG(1)SG(2),其实求SG(1)=SG(2)的方案会更简单些。

fS表示目前只考虑了生成子图SSG(1)=SG(2)的方案数,那么若从T转移到S时我们可以构造一种方案使得T的所有点内的SG加一,然后S/T的所有点的SG0

也就相当于我们把点按照SG大小分成若干层,然后一层一层转移进去。好了现在考虑怎么转移fS,我们枚举它的子集T,那么S/T就是它的下一层,也就是目前S/T内的点SG=0

对于T内的每个点,我们需要连接至少一个S/T内的点,对于S/T内的点,可以随意连接T内的点,枚举一下点集统计方案就好了。

时间复杂度O(3nn)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define ll long long using namespace std; const ll N=15,P=1e9+7; ll n,m,ans,f[1<<N],c[1<<N],e[N]; vector<int>q[N]; signed main() { scanf("%lld%lld",&n,&m); for(ll i=1;i<=m;i++){ ll x,y; scanf("%lld%lld",&x,&y); x--;y--;e[x]|=(1<<y); } ll MS=(1<<n),o=0;c[0]=1; for(ll i=1;i<MS;i++)c[i]=c[i-(i&-i)]*2; for(ll s=0;s<MS;s++){ if((s&1)!=((s>>1)&1))continue; f[s]=1; for(ll t=(s-1)&s;t;t=(t-1)&s){ ll buf=f[t]; for(ll i=0;i<n;i++){ if((t>>i)&1)buf=buf*(c[(s^t)&e[i]]-1)%P; if(((s^t)>>i)&1)buf=buf*c[t&e[i]]%P; } (f[s]+=buf)%=P; } } ll ans=1; while(m)m--,ans=ans*2%P; printf("%lld\n",(ans-f[MS-1]+P)%P); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14879953.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(57)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示