[SDOI2013] 隨機數生成器 題解
阿新 • • 發佈:2020-10-27
Description
給你 \(p,a,b,x_1,t\),定義數列 \(\{x\}:x_i=ax_{i-1}+b\space (x\ge2)\),求最小使 \(x_n=t\) 的 \(n\) 。
\(0\le a,b,x_1,t < p\le 10^9\)
Sol
轉化為等比數列求和:
\[x_{i+1}= a\times x_i+b \]\[x_{i+1}+\frac b{a-1}=a\times x_i+\frac{ab}{a-1} \]\[x_{i+1}+\frac b{a-1}=a(x_i+\frac{b}{a-1}) \]\[x_n+\frac b{a-1}=a^{n-1}(x_1+\frac{b}{a-1}) \]跑 BSGS 即可。
Code
#include<bits/stdc++.h> #define int long long using namespace std; int Read() { int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();} while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x * f; } void Write(int x) { if(x < 0) putchar('-'), x = -x; if(x == 0) putchar('0'); int stk[55], tp = 0; while(x) stk[++tp] = x % 10, x /= 10; for(int i = tp; i; i--) putchar(stk[i] + '0'); } int Mod, a, b, x, t; int qpow(int a, int b) { int res = 1; while(b) { if(b & 1) res = res * a % Mod; a = a * a % Mod; b >>= 1; } return res; } map<int, int> mp; signed main() { int T = Read(); while(T--) { mp.clear(); Mod = Read(), a = Read(), b = Read(), x = Read(), t = Read(); if(x == t) {puts("1"); continue;} if(a == 0) { if(b == t) puts("2"); else puts("-1"); continue; } if(a == 1) { if(b == 0) puts("-1"); else { int nyb = qpow(b, Mod - 2), ans = ((t - x) % Mod + Mod) * nyb % Mod; printf("%lld\n", ans + 1); } continue; } x = ((a - 1) * t % Mod + b) % Mod * qpow((a - 1) * x % Mod + b, Mod - 2) % Mod; int res = x, base = sqrt((double)Mod) + 1; for(int i = 1; i <= base; i++) { mp[res] = i; res = res * a % Mod; } int Res = qpow(a, base), Q = Res, flag = 0; for(int i = 1; i <= base; i++) { if(mp[Res]) { cout << i * base - mp[Res] + 2 << endl; flag = 1; break; } Res = Res * Q % Mod; } if(!flag) puts("-1"); } return 0; }