怎么这么多随机数生成器
题意见原题。
很容易想到\(BSGS\)算法,但是递推式是\(X_{i+1}=(aX_i+b)\mod p\),这显然不是一个等比数列。
但是可以用矩阵乘法来求出第\(i\)项,所以好像可以用\(BSGS\)套矩阵乘法?但是总要把那个常数项除过来吧,矩阵除法是什么鬼?
无奈只好放弃去看题解。
看完之后,哎,我太蒻了。
\[X_{i+1}=(aX_i+b)\mod p\]
\[X_{i+1}=a(X_i+\frac{b}{a})\mod p\]
\[X_{i+1}=(aX_i+\frac{ab}{a})\mod p\]
\[X_{i+1}=(aX_i+\frac{(a-1)b}{a-1})\mod p\]
\[X_{i+1}+\frac{b}{a-1}=(aX_i+\frac{ab}{a-1})\mod p\]
\[X_{i+1}+\frac{b}{a-1}=a(X_i+\frac{b}{a-1})\mod p\]
然后,你发现了什么?
没错,式子两边都有一个\(X+\frac{b}{a-1}\)。
把上面这个式子的左边再乘一个\(a\)就能得到\(X_{i+2}+\frac{b}{a-1}\)。
于是就有
\[X_n+\frac{b}{a-1}=a^{n-1}(X_1+\frac{b}{a-1})\mod p\]
\[\frac{X_n+\frac{b}{a-1}}{X_1+\frac{b}{a-1}}\equiv a^{n-1}\pmod p\]
左边的都是已知的,对左边有理数取余,然后就可以\(BSGS\)了,不会\(BSGS\)的戳这里。
另外对\(a=0,1\)或者\(X_1=t\)要特判一下
#include <cstdio>
#include <map>
#include <cmath>
#include <cstdlib>
#define ll long long
using namespace std;
int fast_pow(int n, int k, int p){ //n^k%p
int ans = 1;
while(k){
if(k & 1) ans = (long long)ans * n % p;
n = (long long)n * n % p;
k >>= 1;
}
return ans;
}
int BSGS(int a, int b, int p){ //a^x≡b(mod p)
map <int, int> hash; hash.clear();
int t = ceil(sqrt(p));
for(int i = 0; i < t; ++i){
int val = (long long)b * fast_pow(a, i, p) % p;
hash[val] = i;
}
a = fast_pow(a, t, p);
if(!a) return !b ? 1 : -1;
for(int i = 0; i <= t; ++i){
int j = fast_pow(a, i, p);
int k = hash.find(j) == hash.end() ? -1 : hash[j];
if(k >= 0 && (i * t - k) >= 0) return i * t - k;
}
return -1;
}
void exgcd(int a, int b, int &x, int &y){
if(!b){
x = 1; y = 0;
return;
}
exgcd(b, a % b, x, y);
int z = x; x = y; y = z - (a / b) * y;
}
int T;
int p, a, b, x, t;
int X, Y;
int main(){
scanf("%d", &T);
while(T--){
scanf("%d%d%d%d%d", &p, &a, &b, &x, &t);
if(x == t) { printf("1\n"); continue; }
if(!a){
if(t == b) printf("2\n");
else printf("-1\n");
continue;
}
if(a == 1 && !b) { printf("-1\n"); continue; }
if(a == 1){
int r = fast_pow(b, p - 2, p);
printf("%d\n",(((((long long)t - x) % p + p) % p) * r % p) % p + 1);
continue;
}
int u = fast_pow(a - 1, p - 2, p);
u = (long long)b * ((u % p + p) % p) %p;
exgcd((x + u) % p, p, X, Y);
X = (long long)(t + u) * ((X % p + p) % p) % p;
int ans = BSGS(a, X, p);
printf("%d\n", ~ans ? ans + 1 : ans);
}
return 0;
}