题目(太长了懒得概括)
题解
用 multiset
预处理出第 (i) 条龙对应的剑攻击力 (s_i) ,可以得到同余方程 (x_i s_i equiv a_i pmod {p_i}) 。
用扩欧求到一个解 (x_i) 后,可以得到 (x = x_i + k dfrac{p_i}{gcd(p_i,s_i)}) 也就是 (x equiv x_i pmod {dfrac{p_i}{gcd(p_i,s_i)} })。
对 (n) 条新的同余方程进行 exCRT 即可。
注意,数据中若不满足特性1,则 (p_i=1) , 所以 (x = maxlimits_{1 leq i leq n} left{ leftlceil dfrac{a_i}{s_i}
ight
ceil
ight}) 。
好像还有其他做法,设前 (i - 1) 个方程的答案为 (ans) , 模数为 (m) ,则前 (i) 个方程的答案应为 (ans gets ans + mx_i) 。
得到 (s_i(ans + mx_i) = a_i pmod {p_i}) 即 ((s_im)x_i = a_i - s_ianspmod {p_i}) 。同样用扩欧即可。
坑点挺多的。。。
注意模数!!!*
会爆 long long
,所以要用慢速乘。
#include <cstdio>
#include <cctype>
#include <set>
using std::multiset;
using std::max;
#define MAX_N (100000 + 5)
#define MAX_M (100000 + 5)
typedef long long LL;
int T;
int n, m;
LL a[MAX_N], p[MAX_N];
int b[MAX_N];
multiset<LL> S;
int s[MAX_N];
LL g;
int Read_Int()
{
int res = 0;
char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
return res;
}
LL Read_LL()
{
LL res = 0;
char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
return res;
}
LL Mul(LL x, LL y, LL mod)
{
LL res = 0;
while (y)
{
if (y & 1) res = (res + x) % mod;
x = (x + x) % mod;
y >>= 1;
}
return res;
}
void exGCD(LL a, LL b, LL & x, LL & y)
{
if (!b)
{
g = a;
x = 1;
y = 0;
return;
}
exGCD(b, a % b, y, x);
y -= a / b * x;
}
LL exCRT()
{
LL ans;
if (p[1] < a[1])
{
ans = 0;
for (int i = 1; i <= n; ++i)
{
ans = max(ans, (a[i] - 1) / s[i] + 1);
}
return ans;
}
LL m, x, y, tmp, last;
exGCD(s[1], p[1], x, y);
if (a[1] % g) return -1;
m = p[1] / g;
x = (x % p[1] + p[1]) % p[1];
ans = Mul(x, a[1] / g, p[1]);
for (int i = 2; i <= n; ++i)
{
exGCD(s[i], p[i], x, y);
if (a[i] % g) return -1;
x = (x % p[i] + p[i]) % p[i];
last = Mul(x, a[i] / g, p[i]);
p[i] /= g;
exGCD(m, p[i], x, y);
if ((last - ans) % g) return -1;
tmp = p[i] / g;
x = (x % tmp + tmp) % tmp;
x = Mul(x, ((last - ans) / g % tmp + tmp) % tmp, tmp);
ans += x * m;
m = m / g * p[i];
ans %= m;
}
return ans % m; // 记得mod!!!
}
int main()
{
T = Read_Int();
multiset<LL>::iterator it;
while (T--)
{
n = Read_Int();
m = Read_Int();
for (int i = 1; i <= n; ++i) a[i] = Read_LL();
for (int i = 1; i <= n; ++i) p[i] = Read_LL();
for (int i = 1; i <= n; ++i) b[i] = Read_Int();
for (int i = 1; i <= m; ++i) S.insert(Read_Int());
for (int i = 1; i <= n; ++i)
{
it = S.upper_bound(a[i]);
if (it != S.begin()) --it;
s[i] = *it;
S.erase(it);
S.insert(b[i]);
}
S.clear();
printf("%lld
", exCRT());
}
return 0;
}