题目大意:
首先我们应该可以看出这是一道\(excrt\)题目
至于剑这个限制其实很\(naive\),用\(multiset\)存一下就好了
根据题意我们可以列出方程组
\[\begin{cases}d_1x\equiv a_1 (mod\ p_1)\\d_2x\equiv a_2 (mod\ p_2)\\……\\d_nx\equiv a_n (mod\ p_n)\end{cases}\]
其中\(d_i\)为剑攻击力,\(x\)为攻击次数,\(a_i\)为龙龙的血量,\(p_i\)为回复能力
毒瘤
但是我们好像有\(a_i>p_i\)的情况……根据题目我们好像不能直接模掉……
然而我们翻过题解之后发现可能存在\(a_i>p_i\)时,全部满足\(p_i=1\)那么我们大力判断掉就好了
具体方法:
\[ans=max\{ \lceil\frac{d_i}{a_i}\rceil \}\]
通解
先考虑\(d_ix\equiv a_i (mod\ p_i)\)好像和一般的\(crt\)方程不太一样,化简一下
\[x*d_i+y*p_i=- a_i\]
用\(exgcd\)求出一组\(x_t,y_t\)
由于\(ecgcd\)通解为\(x=x_t+k*\frac{b}{gcd(a,b)}\),得到\(x=x_t+k*\frac{p_i}{gcd(p_i,d_i)}\)
对\(\frac{p_i}{gcd(p_i,d_i)}\)取模,得到
\(x\equiv x_t (mod\ \frac{p_i}{gcd(p_i,d_i)})\)
然后大力\(excrt\)
注意
我们感性理解一下可以得出\(x\ge (maxn=max\{\lceil\frac{a_i}{d_i}\rceil\})\),如果最后答案小于这个数,应该补上
推出来是\(ret=ret+m*\lceil\frac{maxn-ret}{m}\rceil\)
#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define eps (1e-8)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=1e5+10;
int haku;
int n,m;
int a[N],p[N],sword[N];
inline void exgcd(int &x,int &y,int &g,int a,int b)
{
if(!b){x=1,y=0,g=a;return;}
exgcd(y,x,g,b,a%b);
y-=a/b*x;
}
inline int slow(int x,int k,int p)
{
int ret=0;
while(k)
{
if(k&1) ret=(ret+x)%p;
x=(x+x)%p;
k>>=1;
}
return ret;
}
multiset<int> q;
multiset<int>::iterator it;
inline int excrt()
{
int m=1,ret=0,maxn=0,x,y,g;
for(int i=1;i<=n;++i)
{
it=q.upper_bound(a[i]);
if(it!=q.begin()) --it;
int k=*it;
q.erase(it);
q.insert(sword[i]);
maxn=max(maxn,(a[i]-1)/k+1);
k%=p[i],a[i]%=p[i];
exgcd(x,y,g,k,p[i]);
if(a[i]%g) return -1;
p[i]/=g;
a[i]=slow(a[i]/g,(x%p[i]+p[i])%p[i],p[i]);
int c=((a[i]-ret)%p[i]+p[i])%p[i];
exgcd(x,y,g,m,p[i]);
if(c%g) return -1;
x=slow(x,c/g,p[i]);
ret+=x*m;
m*=p[i]/g;
ret%=m;
}
return ret>=maxn?ret:ret+m*((maxn-ret-1)/m+1);
}
inline void main()
{
haku=read();
while(haku--)
{
n=read(),m=read();
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i) p[i]=read();
for(int i=1;i<=n;++i) sword[i]=read();
for(int i=1;i<=m;++i) q.insert(read());
printf("%lld\n",excrt());
q.clear();
}
}
}
signed main()
{
red::main();
return 0;
}