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]随机数生成器的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3122: [Sdoi2013]随机数生成器

BZOJ 3122 [Sdoi2013]随机数生成器 (BSGS)

bzoj3122: [Sdoi2013]随机数生成器 数论-BSGS

[Sdoi2013]随机数生成器(BSGS)

BZOJ3122SDoi2013随机数生成器

SDOI2013 随机数生成器