P12239 [蓝桥杯 2023 国 Java A] 游戏的得分
Genius_Star · · 题解
思路:
若一个轮数
这是显然的。
于是你可以先 BSGS 求出最小的
问题变为在所有解
每次暴力 BSGS,时间复杂度为
容易发现,问题是P11175 【模板】基于值域预处理的快速离散对数,使用模版题的做法,然后换底公式即可。
本题中没有那么必要开科技,考虑 BSGS 的本质的根号分治平衡,本题由于询问过多,考虑重新设置阈值
-
即对于
1 \le i \le \lceil \frac{\delta_2(p)}{B} \rceil :预处理(A^k)^i 的所有值在哈希表中。 -
然后对于
0 \le i < B :每次计算ba^i 判断是否在哈希表中。
时间复杂度是
完整代码:
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
#define lowbit(x) x & (-x)
#define pi pair<ll, ll>
#define ls(k) k << 1
#define rs(k) k << 1 | 1
#define fi first
#define se second
using namespace __gnu_pbds;
using namespace std;
typedef __int128 __;
typedef long double lb;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
const int p = 998244353, d2 = (p - 1) >> 1, M = 105;
inline ll read(){
ll x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-')
f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return x * f;
}
inline void write(ll x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int T, a, b, m, B;
int pow2[M];
gp_hash_table<int, int> mp;
inline int qpow(int a, int b){
int ans = 1;
while(b){
if(b & 1)
ans = 1ll * ans * a % p;
a = 1ll * a * a % p;
b >>= 1;
}
return ans;
}
inline void init(int a = 2){
pow2[0] = 1;
for(int i = 1; i <= B; ++i)
pow2[i] = 2ll * pow2[i - 1] % p;
m = d2 / B + 1;
// cerr << m << '\n';
int x = pow2[B], now = 1;
for(int i = 1; i <= m; ++i){
now = 1ll * now * x % p;
if(mp.find(now) == mp.end())
mp[now] = i;
}
}
inline int solve(int b){
if(b == 1)
return 0;
int ans = 1e9;
for(int i = 0; i < B; ++i){
int now = 1ll * b * pow2[i] % p;
if(mp.find(now) != mp.end())
ans = min(ans, mp[now] * B - i);
}
return ans == 1e9 ? -1 : ans;
}
inline void solve(){
a = read(), b = read();
ll x0 = solve(a), y0 = solve(b);
// cerr << x0 << ' ' << y0 << '\n';
if(x0 == -1 || y0 == -1){
puts("-1");
return ;
}
while(((x0 + y0) % 3 != 0) || !(max(x0, y0) <= 2ll * min(x0, y0))){
if(x0 < y0)
x0 += d2;
else
y0 += d2;
}
// cerr << x0 << ' ' << y0 << '\n';
write((x0 + y0) / 3);
putchar('\n');
// cerr << (2ll * y0 - x0) / 3 << ' ' << (x0 + y0) / 3 - (2ll * y0 - x0) / 3 << '\n';
}
int main(){
// freopen("A.in", "r", stdin);
T = read();
// B = sqrt(d2 / T);
B = 80;
// cerr << B << '\n';
init(2);
while(T--)
solve();
return 0;
}