P4774 [NOI2018] 屠龙勇士 题解

传送门

题解

思路

由题目可知,一条龙被攻击 \(x\) 次并回复若干次后生命值恰好为 \(0\) 则死亡,可以得出如下式子:

\[\large ATK_i \cdot x \equiv a_i(\mod p_i) \]

可推出,

\[\large x \equiv a_i \cdot ATK_i^{-1}(\mod p_i) \]

需要求 \(ATK_i\) 在模 \(p_i\) 意义下的逆元。
我们自然会想到使用扩展欧几里得算法,但题中数据并不能保证 \(\gcd(ATK_i,p_i)\)。因此,需要将 \(ATK_i\)\(a_i\)\(p_i\) 同时除以 \(\gcd(ATK_i,p_i)\)
此时,如果 \(\gcd(ATK_i,p_i) \nmid a_i\),那么此方程无解,方程组也无解。
于是我们得到了如下式子:

\[\large x \equiv \frac{a_i}{\gcd(ATK_i,p_i)} \cdot [\frac{ATK_i}{\gcd(ATK_i,p_i)}]^{-1}(\mod \frac{p_i}{\gcd(ATK_i,p_i)}) \]

看起来很吓人,但写起来一点也不吓人。
于是我们得到了一个标准的 exCRT 问题。直接套用求解即可。
注意,攻击次数 \(x\) 应当保证每一条龙打 \(x\) 下后生命值都不大于 \(0\)。不然回复不了。

实现

注意多测。
首先需要求出每条龙的 \(ATK\)。类似于求 \(a_i\) 在数组中的前驱。
可以用平衡树实现,但是 注意到标签里并没有平衡树 笔者平衡树写挂了 这样做太麻烦,于是我们使用multiset
在对每一个方程进行转化的过程中和 exCRT 中判断无解。

代码

\(\gcd\) 和 exgcd 就不放了,注意开__int128
对每一个方程进行转化:

bool calc()
{
	for(int i=1;i<=n;i++)
	{
		long long gcd1=gcd(atk[i],p[i]);
		if(a[i]%gcd1)
			return 0;
		atk[i]/=gcd1,p[i]/=gcd1,a[i]/=gcd1;
		__int128 x,y;
		exgcd(atk[i],p[i],x,y);
		b[i]=a[i]*x%p[i];
	}
	return 1;
}

exCRT:

long long exCRT()
{
	for(int i=2;i<=n;i++)
	{
		__int128 x,y;
		__int128 gcd1=exgcd(p[1],p[i],x,y);
		if((b[i]-b[1])%gcd1) return -1;
		x*=(b[i]-b[1])/gcd1;
		x%=p[i]/gcd1;
		b[1]+=p[1]*x;
		p[1]*=p[i]/gcd1;
	}
	b[1]=(b[1]%p[1]+p[1])%p[1];
	return b[1];
}

主体部分:
注意多测

ms.clear();    //multiset
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
	scanf("%lld",&p[i]);
for(int i=1;i<=n;i++)
	scanf("%lld",&rew[i]);
while(m--)
{
	long long tmp;
	scanf("%lld",&tmp);
	ms.insert(tmp);
}
for(int i=1;i<=n;i++)
{
	auto pos=ms.upper_bound(a[i]);
	if(pos!=ms.begin())
		pos--;
	atk[i]=*pos;
	ms.erase(pos);
	ms.insert(rew[i]);
}
long long mtimes=0;
for(int i=1;i<=n;i++)
	mtimes=std::max(mtimes,(long long)((a[i]+atk[i]-1)/atk[i]));	//std::max()比较不了__int128
if(!calc())
	printf("-1\n");
else
{
	long long ans=exCRT();
	if(ans==-1)
	{
		printf("-1\n");
		continue;
	}
	long long tmp1=mtimes/p[1];
	ans+=p[1]*tmp1;
	if(ans<mti)
		ans+=p[1];
	printf("%lld\n",ans);
}

\[\huge End \]

posted @ 2025-01-21 22:58  整齐的艾萨克  阅读(27)  评论(0)    收藏  举报