「Luogu3306」[SDOI2013]随机数生成器

problem

Solution

我们来回忆一下数列递推公式求通项的方法

Yi=Xi+ba1Y_i=X_i+\frac{b}{a-1},则有

Yi=aYi1Yi=ai1Y1Y_i=aY_{i-1}\Rightarrow Y_i=a^{i-1}Y_1

于是题目转化为求解方程

t+ba1ax1(X1+ba1)(modp)t+\frac b{a-1}\equiv a^{x-1}(X_1+\frac b{a-1})\pmod p

ax1t+ba1X1+ba1(modp)\Rightarrow a^{x-1}\equiv\frac{t+\frac b{a-1}}{X_1+\frac b{a-1}}\pmod p

好的,这个东西我们只要用BSGS就可以了

End?


几个细节:

X1=tX_1=t时,直接输出11

a=0a=0时,输出若b=tb=t则输出22,否则无解,X1=tX_1=t的情况已经特判

a=1a=1时,方程实际上为

(x1)btX1(modp)(x-1)b\equiv t-X_1\pmod p

根据裴蜀定理判掉无解,然后直接算x1x-1即可

需要注意的是如果tX1b=p\frac{t-X_1} b=p,则不需要取模直接输出

True End

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#define mp(x,y) (make_pair((x),(y)))
#define inv(x) (fastpow((x),p-2))
using namespace std;
typedef long long ll;

template <typename T>void read(T &t)
{
t=0;int f=0;char c=getchar();
while(!isdigit(c)){f|=c=='-';c=getchar();}
while(isdigit(c)){t=t*10+c-'0';c=getchar();}
if(f)t=-t;
}

int T;

ll p,a,b,X1,t;
ll m;

ll fastpow(ll a,ll b)
{
ll re=1,base=a;
while(b)
{
if(b&1)
re=re*base%p;
base=base*base%p;
b>>=1;
}
return re;
}

map<ll,ll> rec;
void Pre()
{
rec.clear();
ll tmp=1;
for(register int i=0;i<m;++i,tmp=tmp*a%p)
rec.insert(mp(tmp,i));
}

ll BSGS()
{
ll iatm=inv(fastpow(a,m)),tmp=1;
for(register int i=0;i<m;++i,tmp=tmp*iatm%p)
if(rec.find(b*tmp%p)!=rec.end())
return i*m+rec[b*tmp%p];
return -2;
}

ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}

int main()
{
read(T);
while(T--)
{
read(p),read(a),read(b),read(X1),read(t);
if(X1==t)
{
puts("1");
continue;
}
if(a==1)
{
t=(t-X1+p)%p;
if(t%gcd(b,p))
puts("-1");
else
printf("%lld\n",t*inv(b)+1==p?p:(t*inv(b)+1)%p);
continue;
}
if(a==0)
{
printf("%lld\n",b==t?2:-1ll);
continue;
}
b=b*inv(a-1)%p;
b=(t+b)*inv(X1+b)%p;
m=ceil(sqrt(p));
Pre();
printf("%lld\n",BSGS()+1);
}
return 0;
}