【bzoj3122】[Sdoi2013]随机数生成器 BSGS思想的利用
题目描述
给出递推公式 $x_{i+1}=(ax_i+b)\mod p$ 中的 $p$、$a$、$b$、$x_1$ ,其中 $p$ 是质数。输入 $t$ ,求最小的 $n$ ,使得 $x_n=t$ 。若不存在则输出-1。
输入
输入含有多组数据,第一行一个正整数 T ,表示这个测试点内的数据组数。
接下来 T 行,每行有五个整数 p,a,b,X1,t ,表示一组数据。保证 X1 和 t 都是合法的页码。
注意: p 一定为质数
输出
共T行,每行一个整数表示他最早读到第t页是哪一天。如果他永远不会读到第t页,输出-1。
样例输入
3
7 1 1 3 3
7 2 2 2 0
7 2 2 2 1
样例输出
1
3
-1
题解
BSGS思想的利用
(以下为思考过程)
早就知道网上的大部分题解:把通项公式变形为$x_{i+1}+c=a(x_i+c)\mod p$,然后转化为BSGS的经典方程$a^x\mod p=c$来求解。
然而这样需要exgcd之类的,还需要乱七八糟的特判,代码少说也有80+行。
考虑:直接利用BSGS的meet-in-the-middle思想,而不是无脑套方程求解。
(以上为思考过程)
为了方便,设$f(x)=(ax+b)\mod p$,$f^d(x)$表示$f(x)$的$d$次复合,即$f(f(...(x)))$,其中$f$的个数为$d$。
我们要求的就是满足$f^n(x_1)=t$的最小的$n$。
首先根据抽屉(鸽笼)原理,如果有解则一定不超过$p$。
把答案$n$写成$km-l$的形式,其中$m=\lceil\sqrt n\rceil$。
那么我们要求的就是$f^{km-l}(x_1)=t$。
我们把这个式子左右同时复合$l$层,变为$f^{km}(x_1)=f^l(t)$。
由于一次函数复合以后还是一次函数,因此可以直接处理出$f^l(x)$和$f^{km}(x)$中一次项和常数项的系数。具体方法:$a(cx+d)+b=acx+ad+b$。
然后把所有的$f^{km}(x_1)$按照处理出的系数算出来,放到哈希表中(代码中使用了map),其中值相同的只取$k$较小的。
再枚举$l$,按照处理出的系数算出$f^l(t)$,看哈希表中是否有这个数即可,如果有则用$km-l$更新答案。
思考一下为什么一般情况下这样是对的:因为$p$是足够大的质数,因此所有数在模意义下都是存在的,并且存在唯一的逆。所以对于已知的$(cx+d)\mod p=e$,知道$e$可以直接推出$x$。
这个做法当$a=0$时不成立,因为不存在唯一的逆。因此需要特殊处理。
时间复杂度$O(\sqrt n\log n)$
代码只有40行左右^_^
- #include <map>
- #include <cmath>
- #include <cstdio>
- using namespace std;
- typedef long long ll;
- map<ll , ll> mp;
- map<ll , ll>::iterator it;
- ll u[50010] , v[50010];
- int main()
- {
- int T;
- scanf("%d" , &T);
- while(T -- )
- {
- ll p , a , b , x , t , m , i , ans = 1ll << 62;
- scanf("%lld%lld%lld%lld%lld" , &p , &a , &b , &x , &t);
- if(!a)
- {
- if(t == x) puts("1");
- else if(t == b) puts("2");
- else puts("-1");
- }
- else
- {
- mp.clear() , m = ceil(sqrt(p));
- u[0] = 1 , v[0] = 0;
- for(i = 1 ; i <= m ; i ++ ) u[i] = u[i - 1] * a % p , v[i] = (a * v[i - 1] + b) % p;
- for(i = 1 ; i <= m ; i ++ )
- {
- x = (x * u[m] + v[m]) % p;
- if((it = mp.find(x)) == mp.end())
- mp[x] = i;
- }
- for(i = 1 ; i <= m ; i ++ )
- if((it = mp.find((t * u[i] + v[i]) % p)) != mp.end())
- ans = min(ans , it->second * m - i + 1);
- if(ans == 1ll << 62) puts("-1");
- else printf("%lld\n" , ans);
- }
- }
- return 0;
- }
【bzoj3122】[Sdoi2013]随机数生成器 BSGS思想的利用的更多相关文章
- BZOJ3122: [Sdoi2013]随机数生成器(BSGS)
题意 题目链接 Sol 这题也比较休闲. 直接把\(X_{i+1} = (aX_i + b) \pmod P\)展开,推到最后会得到这么个玩意儿 \[ a^{i-1} (x_1 + \frac{b}{ ...
- [bzoj3122][SDOI2013]随机数生成器 ——BSGS,数列
题目大意 给定递推序列: F[i] = a*F[i-1] + b (mod c) 求一个最小的i使得F[i] == t 题解 我们首先要化简这个数列,作为一个学渣,我查阅了一些资料: http://d ...
- bzoj3122 [SDOI2013]随机数生成器
bzoj3122 [SDOI2013]随机数生成器 给定一个递推式, \(X_i=(aX_{i-1}+b)\mod P\) 求满足 \(X_k=t\) 的最小整数解,无解输出 \(-1\) \(0\l ...
- 【BZOJ3122】[Sdoi2013]随机数生成器 BSGS+exgcd+特判
[BZOJ3122][Sdoi2013]随机数生成器 Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数. 接下来T行,每行有五个整数p,a,b, ...
- 【BZOJ-3122】随机数生成器 BSGS
3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1362 Solved: 531[Submit][Sta ...
- 【BZOJ 3122】 [Sdoi2013]随机数生成器 (BSGS)
3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1442 Solved: 552 Description ...
- BZOJ3122 [Sdoi2013]随机数生成器 【BSGS】
题目 输入格式 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数. 接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据.保证X1和t都是合法的页码. 注意:P一定为质数 输出 ...
- bzoj千题计划259:bzoj3122: [Sdoi2013]随机数生成器
http://www.lydsy.com/JudgeOnline/problem.php?id=3122 等比数列求和公式+BSGS #include<map> #include<c ...
- bzoj 3122 : [Sdoi2013]随机数生成器 BSGS
BSGS算法 转自:http://blog.csdn.net/clove_unique 问题 给定a,b,p,求最小的非负整数x,满足$a^x≡b(mod \ p)$ 题解 这就是经典的BSGS算法, ...
随机推荐
- 使用nginx对spring boot项目进行代理
摘要:使用nginx对spring boot项目进行反向代理,并且使用轮询均衡负载策略 均衡负载与集群 集群和均衡都涉及到多个机器提供的服务的问题 不同点是,集群是互相通信.协同的的多个服务,服务之前 ...
- c#winform使用WebBrowser 大全
C# WinForm WebBrowser (一) MSDN资料 1.主要用途:使用户可以在窗体中导航网页. 2.注意:WebBrowser 控件会占用大量资源.使用完该控件后一定要调用 Dispos ...
- YII2.0学习一 Advanced 模板安装
下载github上的完事安装包(本机环境使用Composer安装非常慢) https://github.com/yiisoft/yii2-app-advanced 解压到文件目录 wwwroot/sh ...
- Python基础03
while循坏while属于条件判断 条件满足====>执行 条件不满足====>退出循环 whlie循环格式 while 条件 : 执行语句 while 1 == 1: print(&q ...
- Java学习笔记十二:Java中方法的重载
Java中方法的重载 什么是方法的重载呢? 如果同一个类中包含了两个或两个以上方法名相同.方法参数的个数.顺序或类型不同的方法,则称为方法的重载,也可称该方法被重载了.如下所示 4 个方法名称都为 s ...
- DLX算法一览
目录: 1 X思想的了解. 链表的递归与回溯. 具体操作. 优化. 一些应用与应用中的再次优化(例题). 练手题 X思想的了解. 首先了解DLX是什么? DLX是一种多元未饱和型指令集结构,DLX 代 ...
- Linux(CentOS)安装Node.JS
源码安装 比使用yum安装灵活 1.创建目录 cd /opt mkdir program cd program 2.下载安装包 wget https://nodejs.org/dist/v8.12.0 ...
- python2.7练习小例子(十五)
15):题目:输出指定格式的日期. 程序分析:使用 datetime 模块. 程序源代码: #!/usr/bin/python # -*- coding: UTF-8 -*- ...
- Kotlin 1 函数
#2 函数 函数声明和平时我见到的有点不太一样,使用关键字fun来声明.(感觉好欢乐的样子···O(∩_∩)O~~) 下面的示例,简单的声明了一个函数: // 这是函数声明 fun this_is_a ...
- C++学习009预处理器指令符号 # ## #@ 符号的使用
# ## #@ 符号是预处理器指令符号. 当预处理器遇到#指令符号时,会将#之后的部分用双引号括起来 当预处理去遇到##指令符号时,直接将##前后部分连接起来 当预处理器遇到#@指令符号,将#@之后的 ...