P3306 [SDOI2013]随机数生成器
Posted jackpei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3306 [SDOI2013]随机数生成器相关的知识,希望对你有一定的参考价值。
思路:\(BSGS\)
提交:\(1\)次
题解:
原式可以化为\[x_i+1+\fracba-1=a(x_i+\fracba-1)\mod p\]
这不是等比数列吗?
\[x_n+\fracba-1=a^n-1\cdot (x_1+\fracba-1)\mod p\]
所以有
\[a^n-1=(x_1+\fracba-1)^-1\cdot (x_n+\fracba-1)\mod p\]
这样我们可以\(BSGS\)
注意特判\(a=1,0\)的情况
#include<cstdio>
#include<iostream>
#include<unordered_map>
#include<cmath>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi
template<class I> inline I g(I& x) x=0; register I f=1;
register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
int T,p,a,b,x1,xn;
inline ll qpow(ll a,ll b) register ll ret=1;
for(;b;b>>=1,(a*=a)%=p) if(b&1) (ret*=a)%=p; return ret;
inline int BSGS()
unordered_map<int,int> hsh; hsh.clear();
R t=sqrt(p)+1; R c=(xn+1ll*b*qpow(a-1,p-2))%p*qpow((x1+1ll*b*qpow(a-1,p-2))%p,p-2)%p;
for(R i=1;i<=t;++i)
R vl=1ll*c*qpow(a,i)%p;
hsh[vl]=i;
a=qpow(a,t);
if(a==0) return c==0?1:-2;
for(R i=1;i<=t;++i)
R vl=qpow(a,i);
if(hsh.count(vl)&&i*t-hsh[vl]>=0) return i*t-hsh[vl];
return -2;
inline void main()
g(T); while(T--)
g(p),g(a),g(b),g(x1),g(xn);
if(x1==xn) puts("1"); continue;
if(a==0) if(xn==b) puts("2"); else puts("-1"); continue;
if(a==1&&b==0) puts("-1"); continue;
if(a==1)
printf("%d\n",1ll*((xn-x1)%p+p)%p*qpow(b,p-2)%p+1);
continue;
printf("%d\n",BSGS()+1);
signed main() Luitaryi::main(); return 0;
2019.08.24
76
以上是关于P3306 [SDOI2013]随机数生成器的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 3122 [Sdoi2013]随机数生成器 (BSGS)