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. ...
随机推荐
- 2016.6.21 将Eclipse中项目部署到tomcat下
新建的web项目,各种都配置好,选择run on server之后,发现运行失败,并不能访问需要的网址.而脱离eclipse,将生成的war文件直接放到tomcat的webapp下时,可以正常访问.所 ...
- maven管理整理
maven管理整理 学习了:https://www.imooc.com/learn/443 mvn -v 版本 compile 编译 test 测试 package 打包 clean 删除 insta ...
- 如何把VBS转换为EXE文件
如下所示,我想要做一个把360网速测试剥离开来的绿色版,有一个TestSpeed.bat命令,双击之后去执行了360AppLoader.exe,并且会调用netmon文件夹的NetSpeed.dll文 ...
- html小知识,怎么实现一个td占据2行
<table border="1" width="100%"> <tr> <td rowspan="2"> ...
- quartz 应用到 spring定时任务 执行两次
https://my.oschina.net/superkangning/blog/467487
- 动态载入Layout 与 论Activity、 Window、View的关系
1)动态载入Layout的代码是 getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main, null)); ...
- codeforces 283C
给 n 中 钱币.以及每两种钱币的关系,表示,ai 的 个数 要大于 bi 组合成一个价值val,求方案数,好奇妙的一个处理方式,不得不说又学到了 #include<stdio.h> #i ...
- ios 视图的旋转及应用
有时候,需要做出如下图所示的效果,这就需要用到视图的旋转了 1.首先将旋转的值由角度转换为弧度: #define degreesToRadinas(x) (M_PI * (x)/180.0) 注:M_ ...
- cookie-小总结吧
写入common.js文件,其他页面调用即可: //添加cookie值 function addcookie(name, value, days) { days = days || 0; var ex ...
- WebClient禁止自动重定向
代码如下: public class MyWebClient : WebClient { public bool AllowAutoRedirect { get; set; } = true; pro ...