思路:
如果我们先用multiset把对付没一条龙的攻击力都预处理出来并且设为
ti
t
i
,看样子我们是要求这个
⎧⎩⎨⎪⎪⎪⎪⎪⎪t1x≡a1 (mod p1)t2x≡a2 (mod p2)…tnx≡an (mod pn)
{
t
1
x
≡
a
1
(
m
o
d
p
1
)
t
2
x
≡
a
2
(
m
o
d
p
2
)
…
t
n
x
≡
a
n
(
m
o
d
p
n
)
但是ExCRT里面并没有前面这个 t t ,所以我们先分别把每一个方程解出来,然后每一个方程都可以化为同余式的形式,然后就直接套ExCRT的板子就好啦。值得注意的一点就是这里的并不是求最小正整数解,而是先要用剑把龙的血量砍没,所以最后还要再加上模数直到满足让所有的龙的血量都。
/*==============================
* Author : ylsoi
* Problem : NOI2018 Dragon
* Algorithm ExCRT
* Time : 2018.7.23
* ===========================*/
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;
using namespace std;
void File(){
freopen("loj2721.in","r",stdin);
freopen("loj2721.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=1e5+10;
int T,n,m;
ll a[maxn],p[maxn],t[maxn],lob;
multiset<ll>atk;
multiset<ll>::iterator it;
ll qmul(ll x,ll b,ll mod){
ll ret=0,mul=1;
if(b<0)mul=-1,b=-b;
while(b){
if(b&1)ret=(ret+x)%mod;
x=(x+x)%mod;
b>>=1;
}
return ret*mul;
}
ll exgcd(ll aa,ll bb,ll &x,ll &y){
if(!bb){x=1; y=0; return aa;}
ll d=exgcd(bb,aa%bb,x,y),tmp=x;
x=y; y=tmp-aa/bb*y;
return d;
}
ll get_inv(ll aa,ll bb){
ll x,y,d=exgcd(aa,-bb,x,y); x/=d;
return (x%bb+bb)%bb;
}
bool cal(){
ll x,y,d,dx;
REP(i,1,n){
d=exgcd(t[i],-p[i],x,y);
if(a[i]%d)return false;
dx=abs(p[i]/d);
x=qmul(x,a[i]/d,dx);
x=(x+dx)%dx;
a[i]=x; p[i]=dx;
}
return true;
}
bool work(){
ll x,y,d,tmp,part1,part2;
REP(i,2,n){
d=exgcd(p[i],p[1],x,y);
if((a[i]-a[1])%d)return false;
tmp=p[1]; p[1]=p[1]/d*p[i];
part1=qmul(tmp,(a[i]-a[1])/d,p[1]);
part2=qmul(part1,get_inv(tmp/d,p[i]/d),p[1]);
a[1]=(a[1]+part2)%p[1];
a[1]=(a[1]+p[1])%p[1];
}
return true;
}
int main(){
File();
read(T);
while(T--){
lob=0;
atk.clear();
read(n); read(m);
REP(i,1,n)read(a[i]);
REP(i,1,n)read(p[i]);
REP(i,1,n)read(t[i]);
REP(i,1,m){
ll u; read(u);
atk.insert(u);
}
REP(i,1,n){
it=atk.upper_bound(a[i]);
if(it!=atk.begin())--it;
atk.insert(t[i]);
t[i]=*it;
atk.erase(it);
lob=max(lob,a[i]/t[i]+(a[i]%t[i] ? 1 : 0));
}
if(!cal()){
puts("-1");
continue;
}
if(!work()){
puts("-1");
continue;
}
if(a[1]>=lob)printf("%lld\n",a[1]);
else printf("%lld\n",a[1]+((lob-a[1])/p[1]+((lob-a[1])%p[1] ? 1 : 0))*p[1]);
}
return 0;
}