bzoj5213: [Zjoi2018]迷宫
好题!话说省选的都开始构造了吗
由于有K的倍数的限制所以不妨取模,先建K个点表示0~K-1这些数,第i个点向[i*m,i*m+m]建边。不难发现这是合法的但不一定是最优的
考虑合并等价的点,首先从直观上考虑,当两个点能够转移到的点相同时,它们一定可以合并,但是能够合并的点远远不止这些
考虑一般化,对于两个节点x,y,假设x*m^q=y*m^q (mod K) 那么只要在q步中x和y没有到达0节点的方案,那么x和y就可以合并
具体的,首先0一定不能被删掉,现在考虑q=1时,1~K-1中等价点
把所有数乘m,只有gcd(m,K)的倍数才能表示出来,对于变成同一个数的点就可以去重了(不过并不需要具体实行这一步骤)
然后,对于能够表示出的能够到达0节点的点,无论如何都没有办法合并,把其中还存在的点计入答案(q=1都存在,但是q递增后就变化了)
让q++,把乘完m得出的每个不同的数拿出来继续进行上述操作,每一轮相当于把在第q轮可以到达0节点且在之前的轮中没有被删的节点计入答案,再把恰好在第q轮等价的点去重(感觉用unique表达更贴切)
现在我们目标是快速模拟这个过程,令f(l,K),表示现在要解决的数值域为[1,l],模数为K,考虑如何递归求解
若l<=K/d,没有溢出不会相交,直接返回l即可
仅考虑q=1的情况,在后期继续递归的时候再考虑满足条件。对于以前可以到达0的数为[(K-l),K],那么此时已经可以到达0的数为[K-m*(K-l),K],在这个值域的数的个数为m*(K-l)/gcd(m,K),计入答案(这里可能有点玄学,可以先看下面再回来看)
为了保证值域连续,当把数都变成gcd(m,K)的倍数后,令所有数都除以gcd(m,K)变为连续,此时上界为(K-m*(K-l))/gcd(m,K)(注意m*(K-l)是可以到达0的数的个数,是要保留的部分不参与递归了。用总数减去保留的数量剩下的再变成压缩同余系),相应的同余系大小K也应该变成K/gcd(m,K)
最终继续递归求f((K-m*(K-l))/gcd(m,K),K/gcd(m,K)),注意会有l>K的情况,此时会取遍K/gcd(m,K)直接返回即可
有一个疑问是对于值的改变是否m也应该随之改变?
ccosi(远行客)的说法:(感谢大佬的解答)
你是不是觉得应该乘上m/d?
事实上(k-l)这里已经/d了,所以是直接乘m,下一层的k-m(k-l)就是上一层的k/d-m((k-l)/d)
我的理解是对于每个数我们是乘上而不是加上m,那么域的变化是不影响乘法的
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b){return (a==)?b:gcd(b%a,a);} LL m;
LL solve(LL l,LL K)
{
LL d=gcd(m,K);
if(l<=K/d)return l;
if(K<=(double)m*(K-l))return K/d;
else return m/d*(K-l)+solve((K-m*(K-l))/d,K/d);
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
LL K;
scanf("%lld%lld",&m,&K);
printf("%lld\n",solve(K-,K)+);
} return ;
}
bzoj5213: [Zjoi2018]迷宫的更多相关文章
- 【BZOJ5213】[ZJOI2018]迷宫(神仙题)
[BZOJ5213][ZJOI2018]迷宫(神仙题) 题面 BZOJ 洛谷 题解 首先可以很容易的得到一个\(K\)个点的答案. 构建\(K\)个点分别表示\(mod\ K\)的余数.那么点\(i\ ...
- yyb博客的几道神仙题
该比赛链接 T5 题意: 给你一个\(n\times n\)的网格,开始有\(m\)个被涂成黑色的格子,如果存在三个格子\((x,y)\),\((y,z)\),\((z,x)\)满足\((x,y)\) ...
- yyb省选前的一些计划
突然意识到有一些题目的计划,才可以减少大量查水表或者找题目的时间. 所以我决定这样子处理. 按照这个链接慢慢做. 当然不可能只做省选题了. 需要适时候夹杂一些其他的题目. 比如\(agc/arc/cf ...
- UOJ#375. 【ZJOI2018】迷宫
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ375.html 题解 首先,我们可以建出一个 k 个点的自动机,第 i 个点表示当前数对 k 取模为 i- ...
- C语言动态走迷宫
曾经用C语言做过的动态走迷宫程序,先分享代码如下: 代码如下: //头文件 #include<stdio.h> #include<windows.h>//Sleep(500)函 ...
- POJ 2251 Dungeon Master(3D迷宫 bfs)
传送门 Dungeon Master Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 28416 Accepted: 11 ...
- BFS_Maze_求解迷宫最短路径
/* 10 10 #.######.# ......#..# .#.##.##.# .#........ ##.##.#### ....#....# .#######.# ....#..... .## ...
- 【刷题笔记】I'm stuck! (迷宫)-----java方案
题目描述 : 给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思: '#': 任何时候玩家都不能移动到此 ...
- canvas实例 ---- 制作简易迷宫(一)
这个系列分为两部分,第一部分为迷宫的生成及操作,第二部分为自动寻路算法. 我们先看效果: See the Pen QGKBjm by fanyipin (@fanyipin) on CodePen. ...
随机推荐
- Zookeeper demo增删改查
Zookeeper 的增删改查demo代码 public class SimpleZkClient { private static final String connectString = &quo ...
- overlay和overlay2的区别
docker作为一个容器平台,它有一套自己的存储系统.它支持的driver有overlay,overlay2, aufs等等. 这篇文章主要分析overlay和overlay2的区别. overlay ...
- dubbo服务接口开发者必备调试利器,你值得拥有
dubbo服务接口开发者必备调试利器,你值得拥有 学习了:https://my.oschina.net/vboxtop/blog/1524290 找到了:http://www.vbox.top/?fr ...
- 【Excle数据透视】如何创建一个数据透视表
数据透视表可以汇总.分析.浏览和提供工作表数据或外部数据源的汇总数据 创建方法一 通过”插入”创建,具体操作请看下图: 创建方法二 通过快捷键创建 使用[ALT+D+P]创建 首先按下alt键,然后依 ...
- 多媒体层预览(Media Layer OverView)
音频模块位于多媒体层里.多媒体层包含了图形.音频.视频三种技术.这三种技术会给你带来声觉.视觉上的良好体验. 来看看ios的结构体系以及媒体层上的内容: ...
- 使用构建工具gradle打包时,遇到的中文问题和解决方式
1.使用gradle clean war 命令将项目打成war包.这一过程gradle没有提示报错. 2.将得到的myapp.war复制到tomcat下webapps(部署war包) 3.启动to ...
- shell脚本学习笔记 (流编辑器sed)
sed意为流编辑器(Stream Editor),在Shell脚本和Makefile中作为过滤器使用很普遍,也就是把前一个程序的输出引入sed的输入,经过一系列编辑命令转换为另一种格式输出. sed不 ...
- Option可选值可选值(二)
//: Playground - noun: a place where people can play import Cocoa var str1 = "供选链接和强制拆包的不同. &qu ...
- 字符数组和strcpy
已知strcpy函数的原型是char *strcpy(char *strDest, const char *strSrc);,其中strDest是目的字符串,strSrc是源字符串. (1)Write ...
- SSIS
http://www.cnblogs.com/codefish/category/557802.html