其他分享
首页 > 其他分享> > P3306 [SDOI2013]随机数生成器

P3306 [SDOI2013]随机数生成器

作者:互联网

思路:\(BSGS\)

提交:\(1\)次

题解:

原式可以化为\[x_{i+1}+\frac{b}{a-1}=a(x_{i}+\frac{b}{a-1})\mod p\]
这不是等比数列吗?
\[x_{n}+\frac{b}{a-1}=a^{n-1}\cdot (x_{1}+\frac{b}{a-1})\mod p\]
所以有
\[a^{n-1}=(x_{1}+\frac{b}{a-1})^{-1}\cdot (x_{n}+\frac{b}{a-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

标签:qpow,ch,frac,P3306,ll,生成器,return,SDOI2013,xn
来源: https://www.cnblogs.com/Jackpei/p/11404629.html