2526. 随机数生成器

题目链接

2526. 随机数生成器

W 喜欢读书,尤其喜欢读《约翰克里斯朵夫》。

最近小 W 准备读一本新书,这本书一共有 p 页,页码范围为 0..p1

W 很忙,所以每天只能读一页书。

为了使事情有趣一些,他打算使用 NOI2012 上学习的线性同余法生成一个序列,来决定每天具体读哪一页。

我们用 Xi 来表示通过这种方法生成出来的第 i 个数,也即小 Wi 天会读哪一页。

这个方法需要设置 3 个参数 a,b,X1,满足 0a,b,X1p1,且 a,b,X1 都是整数。

按照下面的公式生成出来一系列的整数。

Xi+1=(aXi+b)modp

其中 modp 表示前面的数除以 p 的余数。

可以发现,这个序列中下一个数总是由上一个数生成的,而且每一项都在 0..p1 这个范围内,是一个合法的页码。

同时需要注意,这种方法有可能导致某两天读的页码完全一样。

W 非常急切的想去读这本书的第 t 页。

所以他想知道,对于一组给定的 a,b,X1,如果使用线性同余法来生成每一天读的页码,最早读到第 t 页是在哪一天,或者指出他永远不会读到第 t 页。

输入格式

输入含有多组数据,第一行一个正整数 T,表示这个测试点内的数据组数。

接下来 T 行,每行有五个整数 pabX1t,表示一组数据。保证 X1t 都是合法的页码。

注意:P 一定为质数。

输出格式

T 行,每行一个整数表示他最早读到第 t 页是哪一天。

如果他永远不会读到第 t 页,输出 1

数据范围

0ap1,
0bp1,
2p109

输入样例:

3 7 1 1 3 3 7 2 2 2 0 7 2 2 2 1

输出样例:

1 3 -1

解题思路

bsgs

对于 Xi+1=(aXi+b)modp,设 Xi+1+c=a(Xi+c),解得 c=b/(a1),则有 Xn+b/(a1)=an1×(X1+b/(a1)),其中 Xn=t,转换得 an1t+b/(a1)X1+b/(a1)(modp),即 bsgs 模板题,另外这里值得一提的是,X1+b/(a1) 可能是 p 的倍数,即不能用逆元处理,特判这部分后另外要求 an1modp 是一个整数,则 t+b/(a1) 也必须要是 p 的倍数才可能有解,而 X1,t 的范围都小于 p,则上下只存在相等的情况,即 an1=1,则 n=1

  • 时间复杂度:O(p)

代码

// Problem: 随机数生成器 // Contest: AcWing // URL: https://www.acwing.com/problem/content/2528/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } int T,p,a,b,x,t; int ksm(int a,int b,int p) { int res=1%p; while(b) { if(b&1)res=1ll*res*a%p; a=1ll*a*a%p; b>>=1; } return res; } int inv(int a,int p) { return ksm(a,p-2,p); } int bsgs(int a,int b,int p) { b%=p; if(1==b)return 0; unordered_map<int,int> hash; int k=sqrt(p)+1; for(int i=0,j=b;i<k;i++) { hash[j]=i; j=(LL)j*a%p; } int ak=1; for(int i=1;i<=k;i++)ak=(LL)ak*a%p; for(int i=1,j=ak;i<=k;i++) { if(hash.count(j))return i*k-hash[j]; j=(LL)j*ak%p; } return -1; } int main() { for(cin>>T;T;T--) { cin>>p>>a>>b>>x>>t; if(a==0) { if(x==t)puts("1"); else if(b==t)puts("2"); else puts("-1"); } else if(a==1) { if(b==0)puts(x==t?"1":"-1"); else cout<<(LL)inv(b,p)*(t-x+p)%p+1<<'\n'; } else { int A=(LL)b*inv(a-1,p)%p; int B=(x+A)%p; if(B==0) puts((-A+p)%p==t?"1":"-1"); else { int C=(t+A)%p; int res=bsgs(a,(LL)C*inv(B,p)%p,p); if(res>=0)cout<<res+1<<'\n'; else puts("-1"); } } } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16793340.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(81)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2021-10-14 蓝桥杯题集
点击右上角即可分享
微信分享提示