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
posted @ 2025-07-11 23:39  fyv233  阅读(7)  评论(0)    收藏  举报