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

转载于:https://www.cnblogs.com/Jackpei/p/11404629.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值