P3306 随机数生成器
\[\begin{align*}
x_{i+1} & \equiv a \times x_i + b \\
x_{i+1} + \frac{1}{b-a} & \equiv a(x_i+\frac{1}{b-a}) \\
\text{等差数列通项公式} \\
x_{n} + \frac{1}{b-a} & \equiv a^{n-1}(x_1 + \frac{1}{b-a}) \\
a^{n-1} & \equiv \cfrac{x_1 + \frac{1}{b-a}}{x_{n} + \frac{1}{b-a}}
\end{align*}
\pmod{p}
\]
在用大步小步算法求解即可。
特殊情况
Detail 1
对于\(x_1= t\)时,直接输出 \(1\)
Detail 2
对于 \(a=0\) 时,\(x_i=b\)
Detail 3
对于a=1时,有 \(x_i \equiv x_1+b(i−1) \pmod{p}\) 那么求解 \(t−x_1≡b(i−1) \pmod{p}\)的系数 \(i−1\) 即可。注意当答案就是 \(p\) 的时候不要再模 \(p\) 了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+10;
map<int, int>h;
long long GCD(long long a, long long b){
return b ? GCD(b, a % b) : a;
}
int qpow(int n, int m, int p){
if(m == 0) return 1;
if(m == 1) return n%p;
int c = qpow(n, m/2, p);
if(m&1) return c*c%p*n%p;
return c*c%p;
}
int inv(int n, int p){
return qpow(n, p-2, p)%p;
}
int BSGS(int a, int b, int p){
if(a%p==0) return -1;
int sqp = sqrt(p)+1;
h.clear();
int x = a;
h[1] = 0;
for(int i=1;i<=sqp;i++){
if(!h.count(x)) h[x] = i;
x=x*a%p;
}
for(int k=0;k<=sqp;k++){
int c = b * inv(qpow(a, k*sqp, p), p)%p;
if(h.count(c)){
return (h[c] + k*sqp);
}
}
return -1;
}
int solve(){
int p=0, a=0, b=0, x=0, t=0;cin>>p>>a>>b>>x>>t;
if(t==x) return 1;
if(a==0) return (t==b) ? 2 : -1;
if(a==1){
t = ((t - x) % p + p) % p;
if (t % GCD(b, p)) return -1;
else{
if ((t*inv(b, p)+1)%p==0) return p;
else return (t*inv(b, p)+1)%p ;
}
}
int f = (t+b*inv(a-1, p)%p)*inv(x+b*inv(a-1, p)%p, p)%p;
int ans = BSGS(a, f, p);
if(ans == -1)return -1;
return ans+1;
}
signed main(){
// freopen("P3306_10.in", "r", stdin);
// freopen("ans.out", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0),cout.tie(0);
int T;cin>>T;
while(T--) cout<<solve()<<'\n';
}
// 5 3 4 0 1

浙公网安备 33010602011771号