分析:
E x c r t Excrt Excrt
用
m
u
l
t
i
s
e
t
multiset
multiset 就可以快速求出要用的剑了 除非你想写平衡树
问题转化成
:
:
:求同余方程组
{
A
t
k
1
x
≡
H
p
1
(
m
o
d
p
1
)
A
t
k
2
x
≡
H
p
2
(
m
o
d
p
2
)
.
.
.
A
t
k
n
x
≡
H
p
n
(
m
o
d
p
n
)
\begin{cases} Atk_1x≡Hp_1~(mod~p_1)\\ Atk_2x≡Hp_2~(mod~p_2)\\ ~~...\\ Atk_nx≡Hp_n~(mod~p_n) \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧Atk1x≡Hp1 (mod p1)Atk2x≡Hp2 (mod p2) ...Atknx≡Hpn (mod pn)
的最小非负整数的解
观察数据表 发现存在
A
t
k
i
>
p
i
Atk_i>p_i
Atki>pi的情况 这样
e
x
c
r
t
excrt
excrt出来的答案是不合题意的 所以特殊搞一搞
这样 a n s = m a x { H p i A t k i } ans=max\{\frac{Hp_i}{Atk_i}\} ans=max{AtkiHpi} 向上取整
其他就
E
x
c
r
t
Excrt
Excrt 但这个带系数 就要再拓展
前
i
−
1
i-1
i−1个方程通解为
x
+
k
t
x+kt
x+kt 最开始可设为
x
=
0
,
t
=
1
x=0,t=1
x=0,t=1
那么要求
A
t
k
i
(
x
+
k
t
)
≡
H
p
i
(
m
o
d
p
i
)
Atk_i(x+kt)≡Hp_i~(mod~p_i)
Atki(x+kt)≡Hpi (mod pi)
拆开移项
A
t
k
i
t
×
k
≡
H
p
i
−
A
t
k
i
x
(
m
o
d
p
i
)
Atk_it\times k≡Hp_i-Atk_ix~(mod~p_i)
Atkit×k≡Hpi−Atkix (mod pi)
未知的只有
k
k
k 那么设
A
=
A
t
k
i
t
,
B
=
H
p
i
−
A
t
k
i
x
,
C
=
p
i
A=Atk_it ,B=Hp_i-Atk_ix,C=p_i
A=Atkit,B=Hpi−Atkix,C=pi
(
(
(即
c
o
d
e
code
code中的
s
w
o
r
d
,
H
P
,
R
e
c
o
v
sword,HP,Recov
sword,HP,Recov 意如其名
)
)
)
那就是解同余方程
A
k
≡
B
(
m
o
d
C
)
Ak≡B~(mod~C)
Ak≡B (mod C)
e
x
g
c
d
exgcd
exgcd即可
然后要用龟速乘 以及得出的是最小非负数解 判一下 0 0 0
CODE:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int T,n,m;
ll a[N],b[N],p[N],add[N],atk[N];
multiset<ll> Sword;
void Pre()
{
Sword.clear();
multiset<ll>:: iterator it;
for(int i=1;i<=m;i++)
Sword.insert(atk[i]);
for(int i=1;i<=n;i++)
{
it=Sword.upper_bound(b[i]);
if(it!=Sword.begin()) it--;
a[i]=*it;
Sword.erase(it);
Sword.insert(add[i]);
}
}
ll mul(ll a,ll k,ll Mod)
{
a=(a%Mod+Mod)%Mod;
k=(k%Mod+Mod)%Mod;
ll res=0;
while(k)
{
if(k&1) (res+=a)%=Mod;
k>>=1;
(a+=a)%=Mod;
}
return res;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll res=exgcd(b,a%b,x,y);
ll k=x;
x=y;
y=k-a/b*y;
return res;
}
ll Excrt()
{
ll ans=0,t=1,sword,HP,Recov,X,Y;
for(int i=1;i<=n;i++)
{
if(p[i]==1)
{
if(b[i]%a[i]) ans=max(ans,b[i]/a[i]+1);
else ans=max(ans,b[i]/a[i]);
continue;
}
sword=a[i]*t%p[i];
HP=((b[i]-a[i]*ans)%p[i]+p[i])%p[i];
Recov=p[i];
ll gcd=exgcd(sword,Recov,X,Y);
if(HP%gcd) return -1;
Recov/=gcd;
X=mul(X,HP/gcd,Recov);
ans+=X*t; t*=Recov;
ans%=t;
}
return ans?ans:t;
}
int main(){
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&b[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&p[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&add[i]);
for(int i=1;i<=m;i++)
scanf("%lld",&atk[i]);
Pre();
printf("%lld\n",Excrt());
}
return 0;
}