前置知识
平衡树(或者multiset<long long>
)
扩展中国剩余定理
扩展欧几里得
开始
我们对于每一条龙,都要杀,并且全部按顺序杀
所以对于一条龙用的剑可以O(nlogn)平衡树搞出来(STL不香??)
那么我们便可以列举出一堆方程组
[egin{cases}
A_1xequiv a_1pmod{m_1}
\
A_2xequiv a_2pmod{m_2}
\
dots
\
A_nxequiv a_npmod{m_n}
end{cases}
]
是不是有点似曾相识?
这就是扩展中国剩余定理!!!
但是他带了系数,咋办?
我们得把左边(A_i)弄无
那么
[ecause A_ixequiv a_ipmod{m_n}
\
herefore A_ix=a_i-m_nk
\
herefore A_ix+m_nk=a_i
]
这就是扩展欧拉定理模板呗
如果无解输出-1
我们搞出(x,k)的值
定义
[egin{cases}
lcm_1=m_1
\
lcm_i=lcm(lcm_{i-1},m_i)
end{cases}
]
很显然
(x)可以加上或减去任意(lcm_{i-1})
于是有了(xequiv x_0+k'lcm_{i-1},k'in Z)
即(xequiv x_0 pmod{lcm_{i-1}})
于是就可以扩展中国剩余定理搞出来了
贴上代码
#include<bits/stdc++.h>
#define N 100011
#define ll long long
using namespace std;
multiset<ll>q;
int n,m;
inline ll mul(ll a,ll b,ll mod){
if(b<0)a=-a,b=-b;
ll ans(0);
while(!!b){
if(b&1)ans=(ans+a)%mod;
a=(a<<1)%mod;
b>>=1;
}
return (ans%mod+mod)%mod;
}
inline void exgcd(ll a,ll b,ll &x,ll &y,ll &d){
if(!b){d=a;x=1;y=0;return;}
exgcd(b,a%b,y,x,d);
y-=a/b*x;
}
ll a[N],p[N],c[N];
inline void init( ){
q.clear( );
scanf("%d%d",&n,&m);
int i;
int op(0);
ll g;
for(i=1;i<=n;++i)
scanf("%lld",&a[i]);
for(i=1;i<=n;++i)scanf("%lld",&p[i]);
for(i=1;i<=n;++i)
scanf("%lld",&c[i]);
while(m--){scanf("%lld",&g);q.insert(g);}
}
inline multiset<ll>::iterator find(ll k){
multiset<ll>::iterator op;
op=q.upper_bound(k);
if(op!=q.begin( ))--op;
return op;
}
inline ll gcd(ll a,ll b){
return !b?a:gcd(b,a%b);
}
inline ll ceil(ll a,ll b){
return (a+b-1)/b;
}
inline ll maxx(ll a,ll b){
return a>b?a:b;
}
ll X,lcm;
inline void work( ){
init( );
int i;
multiset<ll>::iterator k;
ll x,y,d,QWQ(0);
ll P,A;
for(i=1;i<=n;++i){
k=find(a[i]);
exgcd(*k,p[i],x,y,d);
if(a[i]%d!=0){puts("-1");return;}
QWQ=maxx(QWQ,ceil(a[i],*k));
A=mul(x,a[i]/d,p[i]/d);
P=p[i]/d;
if(i==1){
lcm=P;
X=A;
}else{
exgcd(lcm,P,x,y,d);
if((A-X)%d!=0){puts("-1");return;}
x=mul((A-X)/d,x,P/d);
ll qwq(lcm);
lcm=lcm/d*P;
X=(X+(mul(x,qwq,lcm)%lcm+lcm)%lcm)%lcm;
}
q.erase(k);
q.insert(c[i]);
}
if(!X)X=QWQ;
printf("%lld
",X);
}
int main( ){
int t;
// freopen("dragon2.in","r",stdin);
// freopen("ans.out","w",stdout);
scanf("%d",&t);
while(t--)work( );
}