传送
题意
题意有点复杂...懒得概括了...直接看题目吧...
思路
主要过程
首先, 注意到对付龙 \(i\) 的剑的攻击值 \(c_i\) 是一定的, 并可以预先求出来.
我们可以使用 \(std::muliset\) (可重集合) 来存当前有的剑, 并用 \(upper\_bound\) 求出 \(c_i\).
具体来说, 若 \(upper\_bound\) 返回的迭代器 \(iterator = S.begin()\), 则 \(c_i = *iterator\); 否则 \(c_i = *(--iterator)\).
求出 \(c_i\) 后, 我们可以列出一个关于 \(x\) 的线性同余方程组 (\(a < p\)),
\[\left\{ \begin{aligned} c_1 \cdot x &\equiv a_1 \pmod{p_1} \\ c_2 \cdot x &\equiv a_2 \pmod{p_2} \\ c_3 \cdot x &\equiv a_3 \pmod{p_3} \\ &\ \ \vdots \\ c_n \cdot x &\equiv a_n \pmod{p_n} \\ \end{aligned} \right. \]
第一反应是使用 EXCRT (扩展中国剩余定理), 但是这里 \(x\) 的系数不是 \(1\), 所以我们首先要对方程进行转化.
对于方程
\[c \cdot x \equiv a \pmod{p} \]
把它化为不定方程
\[c \cdot x + p \cdot y =a \]
用 exgcd 解出它的一个特解 \(sx\), 通解 \(x\) 即可表示为
\[x \equiv sx \pmod{\frac{p}{(c,p)}} \]
那么上述的方程组就可以化为
\[\left\{ \begin{aligned} x &\equiv sx_1 \pmod{\frac{p_1}{(c_1,p_1)}} \\ x &\equiv sx_2 \pmod{\frac{p_2}{(c_2,p_2)}} \\ x &\equiv sx_3 \pmod{\frac{p_3}{(c_3,p_3)}} \\ &\ \ \vdots \\ x &\equiv sx_n \pmod{\frac{p_n}{(c_n,p_n)}} \\ \end{aligned} \right. \]
然后我们就可以用 EXCRT 愉快地求解了.
特殊情况
1) \(a > p\)
根据题目数据, 当 \(a > p\) 时, 必定满足 \(p=1\). 也就是说, 只要我们把一条龙的生命值降为非正数, 则它一定会死亡, 所以答案 $x = \max_{i=1}^{n} \lceil \frac{a_i}{c_i} \rceil $.
2) \(\forall i, a_i =p _i\)
这时, 方程组形如
\[\left\{ \begin{aligned} c_1 \cdot x &\equiv 0 \pmod{p_1} \\ c_2 \cdot x &\equiv 0 \pmod{p_2} \\ c_3 \cdot x &\equiv 0 \pmod{p_3} \\ &\ \ \vdots \\ c_n \cdot x &\equiv 0 \pmod{p_n} \\ \end{aligned} \right. \]
那么最小非负整数解就是 \(0\), 显然这不符合题意, 所以我们在求解的时候要保证 \(x\) 是正数.
代码
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int _=1e5+7;
int n,m;
ll a[_],p[_],c[_],t[_];
bool fl;
multiset S;
ll gi(){
ll x=0; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+c-'0',c=getchar();
return x;
}
void Init(){
fl=0,S.clear();
n=gi(),m=gi();
for(int i=1;i<=n;i++)
a[i]=gi();
for(int i=1;i<=n;i++){
p[i]=gi();
if(a[i]>p[i]) fl=1;
}
for(int i=1;i<=n;i++)
t[i]=gi();
for(int i=1;i<=m;i++)
S.insert(gi());
for(int i=1;i<=n;i++){
multiset::iterator pt=S.upper_bound(a[i]);
c[i]= pt==S.begin() ?*pt :*(--pt);
S.erase(pt),S.insert(t[i]);
}
}
void Run1(){
ll ans=0;
for(int i=1;i<=n;i++){
ll x= a[i]%c[i] ?a[i]/c[i]+1 :a[i]/c[i];
ans=max(ans,x);
}
printf("%lld\n",ans);
}
ll Gcd(ll a,ll b){ return b ?Gcd(b,b%a) :a; }
ll Mul(ll a,ll b,ll p){ return ((ull)a*b-(ull)((ld)a/p*b)*p+p)%p; } //快(gui)速乘, 防止溢出
ll Exgcd(ll a,ll b,ll &x0,ll &y0){
if(!b){
x0=1,y0=0;
return a;
}
ll x1,y1,d=Exgcd(b,a%b,x1,y1);
x0=y1;
y0=x1-a/b*y1;
return d;
}
bool Solve(ll a,ll b,ll c,ll &d,ll &sx){
ll y0;
d=Exgcd(a,b,sx,y0);
if(c%d) return 0;
sx=Mul(c/d,sx,b/d);
return 1;
}
void Run2(){
for(int i=1;i<=n;i++){
ll d,sx;
if(!Solve(c[i],p[i],a[i],d,sx)){ puts("-1"); return; }
c[i]=sx,p[i]=p[i]/d;
}
for(int i=1;i