P3306 [SDOI2013] Random number generator

Ideas: \ (BSGS \)

Submission: \ (1 \) times

answer:

Original formula can be reduced to \ [x_ {i + 1}
+ \ frac {b} {a-1} = a (x_ {i} + \ frac {b} {a-1}) \ mod p \] This is not geometric sequence it?
\ [x_ {n} + \
frac {b} {a-1} = a ^ {n-1} \ cdot (x_ {1} + \ frac {b} {a-1}) \ mod p \] So there
\ [a ^ {n-1 } = (x_ {1} + \ frac {b} {a-1}) ^ {- 1} \ cdot (x_ {n} + \ frac {b} {a-1 }) \ mod p \]
we \ (BSGS \)
Note Laid sentence \ (a = 1,0 \) case

#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

Guess you like

Origin www.cnblogs.com/Jackpei/p/11404629.html