洛谷P4774 [NOI2018]屠龍勇士 [擴歐,中國剩余定理]
阿新 • • 發佈:2019-04-17
bool set include pen har emp 輸出 tdi con
等於1,那麽直接輸出\(max\{\lceil \frac{a_i}{atk_i}\rceil\}\)即可。
傳送門
思路
首先可以發現打每條龍的攻擊值顯然是可以提前算出來的,拿multiset
模擬一下即可。
一般情況
可以搞出這麽一些式子:
\[
atk_i\times x=a_i(\text{mod}\ p_i)
\]
簡單處理一下就變成這樣:
\[
atk_i\times x +p_i \times y=a_i
\]
顯然可以擴歐搞出一組特解\((x',y')\),那麽就有
\[
x=x'(\text{mod}\ \frac{p_i}{\gcd(atk_i,a_i)})
\]
然後擴展中國剩余定理合並一下即可。
特殊情況
\(a_i>p_i\)時顯然不能用上面的方法,但數據保證此時\(p_i\)
若全部\(a_i=p_i\)時會解出\(x=0\),此時要輸出\(lcm\{a_i\}\)。
\(p_i|atk_i\)時一般是無解的,但如果同時滿足\(p_i=a_i\)那麽這個方程沒有用,可以換成\(x=0(\text{mod}\ 1)\)。
然後就做完啦。
代碼
#include<bits/stdc++.h> clock_t t=clock(); namespace my_std{ using namespace std; #define pii pair<int,int> #define fir first #define sec second #define MP make_pair #define rep(i,x,y) for (int i=(x);i<=(y);i++) #define drep(i,x,y) for (int i=(x);i>=(y);i--) #define go(x) for (int i=head[x];i;i=edge[i].nxt) #define templ template<typename T> #define sz 110010 typedef long long ll; typedef double db; mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);} templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;} templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;} templ inline void read(T& t) { t=0;char f=0,ch=getchar();double d=0.1; while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar(); while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar(); if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();} t=(f?-t:t); } template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);} char __sr[1<<21],__z[20];int __C=-1,__zz=0; inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;} inline void print(register int x) { if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x; while(__z[++__zz]=x%10+48,x/=10); while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n'; } void file() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); #endif } inline void chktime() { #ifndef ONLINE_JUDGE cout<<(clock()-t)/1000.0<<'\n'; #endif } #ifdef mod ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;} ll inv(ll x){return ksm(x,mod-2);} #else ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;} #endif // inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;} } using namespace my_std; int n,m; ll a[sz],p[sz]; ll _[sz]; ll atk[sz]; void work1() { ll ans=0; rep(i,1,n) chkmax(ans,(a[i]+atk[i]-1)/atk[i]); printf("%lld\n",ans); } struct hh{ll a,p;}s[sz]; /*x%p==a*/ ll exgcd(ll a,ll b,ll &x,ll &y){if (!b) return x=1,y=0,a;ll ret=exgcd(b,a%b,y,x);y-=a/b*x;return ret;} ll mul(ll x,ll y,const ll &mod){x=(x%mod+mod)%mod,y=(y%mod+mod)%mod;ll ret=0;for (;y;y>>=1,x=(x+x)%mod) if (y&1) ret=(ret+x)%mod;return ret;} void excrt(ll &ret,ll &mod) { ll a=0,p=1,x,y; rep(i,1,n) { ll g=exgcd(p,s[i].p,x,y),s1=p/g,s2=s[i].p/g; if ((s[i].a-a)%g!=0) return (void)(ret=-1,mod=-1,puts("-1")); exgcd(s1,s2,x,y);x=(x%s2+s2)%s2; ll _p=p/g*s[i].p; a=(a+mul(p,mul(x,(s[i].a-a)/g,s2),_p))%_p; p=_p; } ret=a,mod=p; } void work2() { rep(i,1,n) { if (atk[i]%p[i]==0) { if (a[i]==p[i]) s[i]=(hh){0,1}; else return (void)(puts("-1")); } ll x,y; ll gcd=exgcd(atk[i],p[i],x,y); if (a[i]%gcd!=0) return (void)(puts("-1")); ll mod=p[i]/gcd; x=mul(x,a[i]/gcd,mod); s[i]=(hh){x,mod}; } ll x,mod; excrt(x,mod); if (x==-1&&mod==-1) return; if (!x) { ll ans=1,_,__; rep(i,1,n) ans=ans/exgcd(ans,a[i],_,__)*a[i]; printf("%lld\n",ans); } else printf("%lld\n",x); } void work() { read(n,m); rep(i,1,n) read(a[i]); rep(i,1,n) read(p[i]); rep(i,1,n) read(_[i]); multiset<ll>s; int x; rep(i,1,m) read(x),s.insert(x); rep(i,1,n) { auto it=s.upper_bound(a[i]); if (it!=s.begin()) --it; atk[i]=*it; s.erase(it); s.insert(_[i]); } bool flg=1; rep(i,1,n) flg&=(p[i]==1); if (flg) work1(); else work2(); } int main() { file(); int T;read(T); while (T--) work(); return 0; }
洛谷P4774 [NOI2018]屠龍勇士 [擴歐,中國剩余定理]