怎么这么多随机数生成器
题意见原题。
很容易想到(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
"); continue; }
if(!a){
if(t == b) printf("2
");
else printf("-1
");
continue;
}
if(a == 1 && !b) { printf("-1
"); continue; }
if(a == 1){
int r = fast_pow(b, p - 2, p);
printf("%d
",(((((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
", ~ans ? ans + 1 : ans);
}
return 0;
}