-
可以想到第一次屠龍用的刀是確定的,可以列一個同餘方程 ,然後每次用的刀都可以確定,因此預先確定所有的刀,對100%的數據用EXCRT求解同餘方程組就可以了。
-
怎麼預先確定所有的刀呢?直接寫的話可以離散然後用樹狀數組維護。。。但是有STL
Multiset裏的lower_bound 和upper_bound -
使用exgcd求解一般的同餘方程這裏p可能不是質數,B和p可能不互質,上式可化成
從而用exgcd解出x即可。 -
EXCRT的注意事項:數據範圍都是long long的,直接乘會爆long long, 要用快速乘
-
這個題的坑:用EXCRT直接求出來的最小正整數解可能不是答案,考慮同餘方程之外,題目要求龍的生命值(經過恢復)恰好爲0纔會死去,因此每條龍都有最小攻擊次數。答案應該是通解中滿足>=max{最小攻擊次數}的值。
只是做到理解具體步驟的程度,還不能完全自己寫出來,STL幾乎不會用,同餘化簡要推很久,exgcd,excrt只有有板子的時候纔會寫,會忘記寫快速乘
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <set>
using namespace std;
#define N 100005
typedef long long LL;
int T,n,m;
LL a[N],p[N],btk[N],atk[N],c[N], P;
LL qmul(LL a, LL b, LL P)
{
LL res = 0;
while (b)
{
if (b & 1) res = (res + a) % P;
a = (a + a) % P;
b >>= 1;
}
return res;
}
LL exgcd(LL a, LL b, LL & x, LL & y)
{
if (b == 0) {x = 1;y = 0;return a;}
LL d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
LL excrt()
{
LL M = p[1], ans = a[1], x, y;
for (int i=1;i<=n;i++)
{
LL d = exgcd(M, p[i], x, y), c = ((a[i] - ans) % p[i] + p[i]);
LL tmp = p[i] / d;
if (c % d != 0) return -1;
x = qmul(x, c / d, tmp);
ans += x * M;
M = M * tmp;
ans = (ans % M + M) % M;
}
P = M;
return ans;
}
LL solve()
{
multiset<LL> S;
for (int i=1;i<=m;i++)
S.insert(atk[i]);
multiset <LL>:: iterator it;
LL tmp = 0;
for (int i=1;i<=n;i++){
it = (a[i] < (*S.begin())) ? S.begin():(--S.upper_bound(a[i]));
c[i] = *it;
S.erase(it);
S.insert(btk[i]);
tmp = max(tmp, ((a[i]-1) / c[i] + 1));//上取整
}
//化簡同餘方程
for (int i=1;i<=n;i++)
{
LL x, y;
LL d = exgcd(c[i], p[i], x, y);
if (a[i] % d != 0) return -1;
x = (x % p[i] + p[i]) % p[i];
a[i] = qmul(x, a[i] / d, p[i]);//! 還是在模p[i]的意義下
p[i] /= d;
}
LL ans = excrt();
if (ans != -1 && ans < tmp)
ans = ans + ((tmp - ans - 1) / P + 1) * P;//上取整
return ans;
}
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i=1;i<=n;i++) scanf("%lld", &a[i]);
for (int i=1;i<=n;i++) scanf("%lld", &p[i]);
for (int i=1;i<=n;i++) scanf("%lld", &btk[i]);
for (int i=1;i<=m;i++) {scanf("%lld", &atk[i]);}
printf("%lld\n", solve());
}
}