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

posted @ 2019-09-03 13:17  LuitaryiJack  阅读(189)  评论(0编辑  收藏  举报