思路是对于 xi×ki≡ai(modpi) 用 exgcd 求出一组特解,然后之后的同余方程模数应该是 gcd(pi,ki)pi,就转化为一个正常的同余方程,最后 exCRT。
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int gcd(int a,int b) { return !b?a:gcd(b,a%b); }
int lcm(int a,int b) { return a/gcd(a,b)*b; }
int n,m;
int a[100010],p[100010];
int g[100010];
multiset<int> st;
int k[100010]; // x*k_i=a_i(mod p_i)
pair<int,int> exgcd(int a,int b)
{
if(!b) return {1,0};
pair<int,int> lst=exgcd(b,a%b);
return {lst.second,lst.first-lst.second*(a/b)};
}
pair<int,int> exgcd1(int a,int b)
{
int g=gcd(a,b);
return exgcd(a/g,b/g);
}
pair<int,int> exgcd2(int a,int b,int d)
{
pair<int,int> ans=exgcd1(a,b);
int g=gcd(a,b);
return {ans.first*(d/g),ans.second*(d/g)};
}
int nowa,nowb;
bool excrt(int a,int b)
{
if((a-nowa)%gcd(nowb,-b)) return 1;
pair<int,int> now=exgcd2(nowb,-b,a-nowa);
__int128 x1=nowa+(__int128)nowb*now.first;
nowb=lcm(nowb,b),nowa=(x1%nowb+nowb)%nowb;
return 0;
}
void solve()
{
cin>>n>>m;
for(int i=1; i<=n; ++i) cin>>a[i];
for(int i=1; i<=n; ++i) cin>>p[i];
for(int i=1; i<=n; ++i) cin>>g[i];
st.clear();
for(int i=1; i<=m; ++i)
{
int x; cin>>x;
st.insert(x);
}
int ax=0; // x 必须要大于的数
for(int i=1; i<=n; ++i)
{
auto wz=st.upper_bound(a[i]);
if(wz!=st.begin()) --wz;
k[i]=(*wz);
st.erase(wz),st.insert(g[i]);
ax=max(ax,(a[i]+k[i]-1)/k[i]);
}
for(int i=1; i<=n; ++i)
{
if(a[i]%gcd(k[i],p[i])) return cout<<-1<<'\n',void();
int x1=exgcd2(k[i],p[i],a[i]).first;
p[i]/=gcd(k[i],p[i]),a[i]=(x1%p[i]+p[i])%p[i];
}
nowa=0,nowb=1;
for(int i=1; i<=n; ++i)
{
if(excrt(a[i],p[i])) return cout<<-1<<'\n',void();
}
cout<<nowa+nowb*((ax-nowa)/nowb)<<'\n';
}
signed main()
{
freopen("1.in","r",stdin);
int t; cin>>t;
while(t--) solve();
return 0;
}