题解
首先,每条龙使用哪把剑是确定的,我们可以根据题意使用 multiset m u l t i s e t (可重集)求出.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
using namespace std;
#define For(i, j, k) for(int i = (j), r__ = (k); i <= r__; i ++)
typedef long long LL;
const int MAXN = 1e5 + 2;
static int n, m;
static int gatk[MAXN], sw[MAXN];
static LL a[MAXN], p[MAXN];
multiset<int> sword;
LL gcd(LL a, LL b) {
return b == 0 ? a : gcd(b, a % b);
}
void exgcd(LL a, LL b, LL & x, LL & y, LL & g) {
if(!b) x = 1, y = 0, g = a;
else exgcd(b, a % b, y, x, g), y -= x * (a / b);
}
LL inv(LL a, LL p) {
LL x, y, g;
exgcd(a, p, x, y, g);
return g == 1 ? (x % p + p) % p : -1;
}
LL d, res;
LL mul(LL a, LL b, LL p) {
if(p <= (LL)(1e9)) return 1ll * a * b % p;
if(p <= (LL)(1e12)) return (((a * (b >> 20) % p) << 20) % p + a * (b & ((1 << 20) - 1))) % p;
d = (LL)floor(a * (long double) b / p);
res = (a * b - d * p) % p;
if(res < 0) res += p;
return res;
}
static LL c[MAXN], mod[MAXN];
bool excrt(LL & ans, LL & lcm) {
LL C = c[1] % mod[1], Mod = mod[1], g, x, y, tmp;
For(i, 2, n) {
c[i] %= mod[i];
exgcd(Mod, mod[i], x, y, g);
if((c[i] - C) % g != 0) return false;
tmp = mod[i] / g;
x = mul(x % tmp, ( (c[i] - C) / g ) % tmp, tmp);
x = (x + tmp) % tmp;
C += mul(Mod, x, Mod * tmp);
Mod *= tmp;
}
ans = (C % Mod + Mod) % Mod;
lcm = Mod;
return true;
}
int main() {
multiset<int> :: iterator j;
int T, g, atk;
LL mx, ans, lcm;
bool no_res;
for(scanf("%d", &T); T --; ) {
sword.clear();
scanf("%d%d", &n, &m);
For(i, 1, n) scanf("%lld", &a[i]);
For(i, 1, n) scanf("%lld", &p[i]);
For(i, 1, n) scanf("%d", &gatk[i]);
For(i, 1, m) {
scanf("%d", &atk);
sword.insert(atk);
}
mx = 0;
For(i, 1, n) {
j = sword.upper_bound(a[i] > 2e9 ? int(2e9) : a[i]);
if(j != sword.begin()) j --;
sw[i] = * j;
sword.erase(j);
sword.insert(gatk[i]);
mx = max(mx, (a[i] + sw[i] - 1) / sw[i]);
}
no_res = false;
For(i, 1, n) {
g = gcd(gcd(sw[i], a[i]), p[i]);
sw[i] /= g; a[i] /= g; p[i] /= g;
if(gcd(sw[i], p[i]) != 1) {
no_res = true;
break ;
}
c[i] = mul(a[i] % p[i], inv(sw[i], p[i]) % p[i], p[i]);
mod[i] = p[i];
}
ans = -1;
if(!no_res) no_res = !excrt(ans, lcm);
if(!no_res && ans < mx)
ans += lcm * ((mx - ans + lcm - 1) / lcm);
printf("%lld\n", no_res ? -1LL : ans);
}
return 0;
}