P4774 [NOI2018]屠龙勇士
昨天晚上快走时看了这题:不是exgcd+excrt吗?
旁边张大佬默默看了我一眼(觉得我会死)
然后于是我今天中午才调出来Orz
思路:exgcd+excrt
提交:5次
错因:龟速乘传进去了负数,并且用的int;之前写过的excrt的板子有问题
题解:
先要特判一种情况:若 \(p[i]=1\) ,答案显然就是 \(\max(\lceil\frac{a[i]}{stk[i]}\rceil)\) ,只需要把龙打成负血他就死了。
先是这样的一些方程:设 \(atk[i]\) 表示对于第 \(i\) 只龙使用攻击力为 \(atk[i]\) 的剑
\[atk[i]*x_i \equiv a[i] \mod p[i]
\]
好的这样我们可以 exgcd 解出 \(X_i=x_i*\frac{a[i]}{gcd(atk[i],p[i])}\)
我们知道,对于上面的方程来说,\(X_i+k*\frac{p[i]}{gcd(atk[i],p[i])},k\in Z\)
设 \(b[i]=\frac{p[i]}{gcd(atk[i],p[i])}\) ,所以对于最终答案\(ans\)有:
\[ans\equiv X_i \mod b[i]
\]
这个 \(ans\) 是可以用 excrt 合并的。
代码:
#include<bits/stdc++.h>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0; register I f=1;
register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
}
template<class I> inline I ps(I x) { if(x<0) putchar('-'),x=-x;
static char s[40]; register int sz=0;
while(x!=0) s[++sz]=x%10,x/=10;
while(sz) putchar(s[sz]+'0'),--sz;
}
const int N=100010;
inline ll exgcd(ll& x,ll& y,ll a,ll b) {
if(!b) {x=1,y=0; return a;}
register ll d=exgcd(y,x,b,a%b); y-=a/b*x;
return d;
}
int T,n,m;
ll s[N],b[N],c[N],a[N],mx;
multiset<ll> ss; bool flg;
multiset<ll>::iterator it;
inline ll mul(ll a,ll b,ll p) { register ll ret=0;
for(;b;b>>=1,a=(a+a)%p) if(b&1) ret=(ret+a)%p;
ret=(ret+p)%p; return ret;
}
inline void main() {
g(T); while(T--) { mx=0,flg=true;
register ll ans=0,sum=1,x,y;
g(n),g(m); for(R i=1;i<=n;++i) g(s[i]);
for(R i=1;i<=n;++i) g(b[i]),flg&=b[i]==1;
for(R i=1;i<=n;++i) g(c[i]);
for(R i=1;i<=m;++i) g(x),ss.insert(x);
for(R i=1;i<=n;++i) {
it=ss.upper_bound(s[i]);
if(it!=ss.begin()) --it;
a[i]=*it,ss.erase(it),ss.insert(c[i]);
mx=max((s[i]+a[i]-1)/a[i],mx);
} if(flg) {
printf("%lld\n",mx);
goto end;
}
for(R i=1;i<=n;++i) { register ll x,y;
register ll d=exgcd(x,y,a[i],b[i]);
if(s[i]%d) {puts("-1"); goto end;}
b[i]/=d,x=(x%b[i]+b[i])%b[i];
s[i]=mul(x,((s[i]/d)%b[i]+b[i])%b[i],b[i]);
}
for(R i=1;i<=n;++i) {
register ll d=exgcd(x,y,sum,b[i]);
if((s[i]-ans)%d) {puts("-1"); goto end;}
b[i]/=d;
x=mul(x,((s[i]-ans)/d%b[i]+b[i])%b[i],b[i]);
ans+=x*sum,sum=sum*b[i];
} printf("%lld\n",(ans%sum+sum)%sum);
end:ss.clear();
}
}
} signed main() {Luitaryi::main(); return 0;}
2019.09.03
66