初见安~这里是传送门:洛谷P3306 [SDOI2013] 随机数生成器
题解
显然我们可以写出一个式子:
后面一坨等比数列求和:
简单移项:
于是这就是一个BSGS的板子了。而且p还是质数。
然后你就可以获得全WA的好成绩【?
因为这个题真正毒的地方在于特判……
我们回头再看看我们的推导过程:
首先对等比数列求和。等等,这真的是等比数列么?
a=0的时候,是个等差数列。这个必须特判。
a=1的时候,是常值。这个情况看似直接用t-x1除以b就好,但是除数部分就只剩下b了。b也可能为0。
上述特判后,这个题就可以过了。
复杂度,上代码——
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#define maxn 100005
using namespace std;
typedef long long ll;
int read() {
int x = 0, f = 1, ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
return x * f;
}
int T, mod, a, b, x1, t, sq;
map<int, int> mp;
int pre[maxn];
int pw(int a, int b) {int res = 1; while(b) {if(b & 1) res = 1ll * res * a % mod; a = 1ll * a * a % mod, b >>= 1;} return res;}
signed main() {
T = read();
while(T--) {
mod = read(), a = read(), b = read(), x1 = read(), t = read();
if(x1 == t) {puts("1"); continue;}
if(!a) {if(t == x1) puts("1"); else if(t == b) puts("2"); else puts("-1"); continue;}
if(a == 1) {
if(!b) puts("-1");
else printf("%d\n", 1ll * (t - x1 + mod) * pw(b, mod - 2) % mod + 1);
continue;
}//好了特判完了。
sq = sqrt(mod); mp.clear();
b = (1ll * t * (1 - a + mod) % mod - b + mod) % mod * pw(1ll * x1 * (1 - a + mod) % mod - b + mod, mod - 2) % mod;
pre[0] = 1; register int tmp = 1; mp[1] = 0;
for(int i = 1; i <= sq; i++) {//BSGS预处理根号内的值
tmp = 1ll * tmp * a % mod;
if(!mp[tmp]) mp[tmp] = i;
}
tmp = pw(pw(a, sq), mod - 2);//其实完全不必预处理的……
for(int i = 1; i <= sq; i++) pre[i] = 1ll * pre[i - 1] * tmp % mod;
bool flag = false;
for(int i = 0; i <= sq; i++) {//ans=i*sqrt()+j 枚举i
tmp = 1ll * b * pre[i] % mod;//记得+1 因为求的是n-1
if(mp[tmp] || tmp == 1) {printf("%d\n", i * sq + mp[tmp] + 1); flag = true; break;}
}
if(!flag) puts("-1");
}
}
迎评:)
——End——