[题目记录]AGC016F Games on DAG

news/2025/1/10 15:46:08/文章来源:https://www.cnblogs.com/youlv/p/18664100

AGC016F Games on DAG

题意

给定一个 \(n\) 个点 \(m\) 条边的 DAG , 在 \(1,2\) 点各有一个石头 , 每次可以沿 DAG 的边移动一个石头 ( 两个石头可以重合 ) , 不能移动者输 , 求只保留一部分边的 \(2^m\) 种方案中 , 先手必胜的个数 .

\(10^9+7\) 取模 .

保证对于每条边 \(u \to v\)\(u<v\) .

\(n\le 15 , m\le \frac{n(n-1)}{2}\) .


题解

题意等价于对每种方案算出 \(1\) , \(2\) 点的 \(SG\) 函数值 , 求 \(SG_1\ne SG_2\) 的情况数 .

考虑在拓扑排序过程中状压 dp , 发现转移要用到当前确定的所有点的 \(SG\) 值 , 也就是说状态只能记录所有 \(SG\) 值 , 这和暴力没有区别 .

换一个角度 , 整体把 \(SG\) 函数相同的所有点分到同一层 , 一次直接填同一层的所有点 . 考虑当前填入的 \(SG\) 值是 \(i\) , 要覆盖的集合是 \(T\) . 此时所有点被分成三部分 , \(SG\) 函数是 \([0,i-1]\) 的已经填完的集合 \(S\) , 当前集合 \(T\) , 以及还没确定的集合 \(Q=\complement(S\cup T)\) .

考虑这个划分是否合法 , 将原图中的边分类讨论 :

  • \(T\) 内部的边 , 全都不能取 .
  • \(T\to S\) 的边 , 要求 \(T\) 内部的每个点 \(u\) 能到达的点中 , \(SG\)\([0,i-1]\) 都要有 .
  • \(T\to Q\) 的边 , 没有影响 , 可以任意取 .

除此之外还有个题目条件 \(SG_1\ne SG_2\) , 直接保证 :

  • \(1,2\) 不同时出现在 \(T\) 中 .

第一部分不用管 , 第三部分可以直接 \(2^k\) 计算系数 , 问题出在了第二部分 , 这又要求我们记录具体的点的 \(SG\) 值了 , 这是我们不想要的 .

所以把第二部分转化一下 , 从限制 \(T\) 里的点 , 变成限制 \(S\) 里的点 :

  • \(SG\) 函数为 \(j\) 的集合为 \(S_j\) , 对 \(T\) 中所有点都要有 \(S_j\to T\) 的边 .

把限制转移到填 \(SG\) 函数这一步 , 就变成了 :

  • 对于 \(Q\) 内部的所有点 , 要有 \(T\to Q\) 的边 .

这样就好处理了 , 枚举 \(Q\) 中每个点 , 如果没有 \(T\to Q\) 的边直接不可行 , 否则至少保留一条 , 系数是 \(2^k-1\) .


状态设 \(f_{i,S}\) 为填完 \(SG=i\) 的部分后 , 已经填完了 \(S\) 的情况数 , 每次枚举填 \(i+1\) 的集合 \(T\) 转移 .

复杂度 , 每次转移相当于子集枚举是 \(3^n\) , 单次转移需要枚举点 , 是 \(O(n)\) 的 , 总共 \(n\) 层 , 复杂度 \(O(n^23^n)\) .


考虑优化 , 单次转移的 $O(n) $ 可以通过预处理去除 , 但是要求的空间是 \(n3^n\) 过大 .

优化状态 , 状态里的 \(i\) 没有起什么作用 , 我们并不关心具体的 \(SG\) 的值 , 把状态直接简化为 \(f_S\) , 表示填完了 \(S\) 的状态数 .

这里可以理解为 \(f_S=\sum \limits_ i f'_{i,S}\) , 每次转移相当于整体进行了 \(f'_{i,S} \to f'_{i+1,S \cup T}\) , 因此是正确的 .

复杂度是 \(O(n3^n)\) , 可以通过 .

点击查看代码
#include<bits/stdc++.h>
#define file(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define ll long long
#define INF 0x3f3f3f3f
#define INF64 1e18
using namespace std;constexpr int N=20;
constexpr int M=(1<<15)+5;
constexpr ll p=1e9+7;int to[N],cnt[M];int n,m;ll f[M],num[N*N];int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;to[u]|=(1<<(v-1));}for(int s=0;s<=(1<<n)-1;s++) cnt[s]=__builtin_popcount(s);num[0]=1;for(int i=1;i<=n*n;i++) num[i]=num[i-1]*2%p;f[0]=1;for(int s=0;s<=(1<<n)-1;s++){if(!f[s]) continue;int T=(s^((1<<n)-1));for(int t=T;t;t=(t-1)&T){if((t&1)&&(t&2)) continue;ll k=1;for(int i=1;i<=n;i++){if(s&(1<<(i-1))) continue;if(t&(1<<(i-1))){k=k*num[cnt[to[i]&(((1<<n)-1)^s^t)]]%p;}else{if((to[i]&t)==0) k=0;else k=k*(num[cnt[to[i]&t]]-1)%p;}}f[s|t]=(f[s|t]+f[s]*k%p)%p;}}cout<<f[(1<<n)-1];
}

总结

这道题的关键是设计一个能方便地进行 \(SG\) 转移的状态 , 最后通过按值域分层找到了一个能状压转移的状态 . 此外 , 把不容易处理的限制转化成容易处理的限制非常重要 .

不过似乎普遍的题解做法是拿整体减钦定 \(1\) , \(2\) 不同的情况 , 并且大多直接设计了 \(f_S\) 的状态 . 自己想的过程额外设计了 \(i\) 维度 , 后来多一个 \(n\) 怎么也去不掉的时候才发现 \(i\) 没有意义 . 不管思路是怎样的 , 最终都导向了相同的状态 . 体现了状态设计一定要抓住一个局面有关键性意义的信息 .

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/867187.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

异地多活架构进阶:如何解决写后立即读场景问题?【转】

在《醍醐灌顶!异地多活架构设计看这篇就够了》一文中,基于容灾需要,讨论了数据写入的架构模型。数据读取方面,重点在于解决读取请求的负载分担、路由选择的问题,对于容灾架构的选择影响不大。不过,其中的“写后立即读”场景,是个一致性范畴的问题,即写入的数据和写入后…

JAVA之面向对象

1、设计对象并使用类和对象 类(设计图):是对象共同特征的描述; 对象:是真实存在的具体实例; 在java中,必须先设计类,才能获得对象。 如何得到类的对象:类名 对象名 = new 类名(); 如何使用对象: 访问属性:对象名.成员变量 访问行为:对象名.方法…

免费手动打Windows Server补丁

免费手动打Windows Server 2008 R2补丁https://catalog.update.microsoft.com/search.aspx?q=kb4474419然后到windows上双击运行即可本文来自博客园,作者:六月OvO,转载请注明原文链接:https://www.cnblogs.com/chenlifan/p/18664077

pwn1_sctf_2016 1

打开ida反汇编看一下,是c++,无所谓,复制问一下ai先让我们输入s的数据,读取长度限制在32字节。然后replace函数会将s里面的 I 替换成 you 。最后输出s。 分析一下,s距离ebp为0x3C(60字节),且我们最多只能输入32字节的,但经过replace函数,一个字节的‘I’会被替换成三个…

UDS-ECU程序刷写

UDS(unified diagnostic services)统一诊断服务主要是针对汽车上对ECU进行诊断服务规范,下图是UDS在OSI分层中的具体规范,基于UDS的刷写应用逻辑体现在应用层的ISO14229规范。一、功能介绍 UDS(unified diagnostic services)统一诊断服务主要是针对汽车上对ECU进行诊断服…

主体分割技术,提升图像信息提取能力

在智能设备普及和AI技术进步的推动下,用户对线上互动的质量、个性化以及沉浸式体验的追求日益增强。例如,对于热衷于图片编辑或视频制作的用户来说,他们需要一种快速而简便的方法来将特定主体从背景中分离出来。 HarmonyOS SDK 基础视觉服务(Core Vision Kit)提供主体分割…

qt 实现窗口置顶,qtdesigner创建的widget窗口集成程序里的用法

参考 https://blog.csdn.net/Larry_Yanan/article/details/123518788 .ui文件如下新建的ui文件,编译一下就会生成对应的 ui_xxx.h 文件,文件内就有对应的 namespace Ui 声明的变量,这个变量要在mainwindow.h中声明,然后在mainwindow.cpp中new出来,具体使用如下 mainwindow…

如何在市场推广活动中实现精准的任务分配?5个项目管理技巧

一、引言 随着市场竞争的加剧和消费者需求的多样化,企业对市场推广活动的要求越来越高。市场推广活动不仅需要创意和精准的目标定位,还需要高效的执行和完善的管理。在这种背景下,如何通过有效的活动管理来提升推广活动的执行力,已成为市场团队面临的一个巨大挑战。 市场推…

Android编译 - 证书介绍

前言全局说明一、说明 1.1 环境: Android1.2 简介 在Android系统中,每个APK文件必须有一个有效的数字证书来证明其来源和完整性。当需要修改APK后再次发布时,原有的签名将不再有效,因此需要重新签名。二、证书工具 2.1 路径: android/build/tools/releasetools/sign_target…

域名解析的QPS防护值是什么?

在当今数字化的时代,互联网已经渗透到生活的方方面面,而域名解析作为互联网运行的关键环节之一,起着至关重要的作用。其中,域名解析的QPS防护值更是保障网络稳定、安全与高效的一个重要指标。 一、QPS 防护值的定义与内涵 QPS,即Queries Per Second,意为每秒查询次数。域…

远程开机详细教程

要实现远程开机,被控端必须满足以下条件: 1.目前仅支持windows系统实现远程开机 2.被控端所在局域网内,需要有另一台设备保持todesk在线 如:其他电脑、iPhone、iPad、Android 设备(手机、平板)、家人的手机(充当辅助开机设备) 如图,辅助开机设备需显示在线,离线状态无法发…

CH585的SPI驱动WS2812

目录 链接: https://pan.baidu.com/s/1Su5dgmVWLre5kH2fYiGwQQ?pwd=wch6 CH573系列/583系列/592系列MCU,在使用SPI模拟WS2812波形时,MISO-PA15引脚上的实时电平,会影响MOSI-PA14引脚上的空闲电平状态,故建议SPI驱动WS2812的场景下,固定PA15的电平,不要接其他外设。异常场…