1. 程式人生 > >BZOJ5418 NOI2018屠龍勇士(excrt)

BZOJ5418 NOI2018屠龍勇士(excrt)

  顯然multiset求出每次用哪把劍。注意到除了p=1的情況,其他資料都保證了ai<pi,於是先特判一下p=1。比較坑的是還可能存在ai=pi,稍微考慮一下。

  剩下的部分即解bix≡ai(mod pi)方程組。沒有保證模數互質,於是excrt一發。excrt實際上就是不停exgcd合併兩個方程。

  這次是重開這題,調了半天還是一堆-1覺得這個題可能是搞不會了,最後才發現某個地方沒開long long。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include
<cstring> #include<algorithm> #include<set> #include<cassert> using namespace std; #define ll long long #define N 100010 char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;} ll gcd(ll n,ll m){return
m==0?n:gcd(m,n%m);} ll lcm(ll n,ll m){return n*(m/gcd(n,m));} ll read() { ll x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int T,n,m; ll b[N],p[N],a[N],rwd[N]; multiset
<ll> q; ll ksc(ll a,ll b,ll p) { ll t=a*b-(ll)((long double)a*b/p+0.5)*p; return t<0?t+p:t; } void exgcd(ll a,ll b,ll &x,ll &y) { if (b==0) { x=1,y=0; return; } exgcd(b,a%b,x,y); ll t=x;x=y;y=t-a/b*x; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj5418.in","r",stdin); freopen("bzoj5418.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif T=read(); while (T--) { n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=n;i++) p[i]=read(); for (int i=1;i<=n;i++) rwd[i]=read(); q.clear(); for (int i=1;i<=m;i++) q.insert(read()); for (int i=1;i<=n;i++) { multiset<ll>::iterator it=q.upper_bound(a[i]); if (it!=q.begin()) it--; b[i]=*it;q.erase(it);q.insert(rwd[i]); } bool issp=1; for (int i=1;i<=n;i++) if (p[i]!=1) {issp=0;break;} ll ans=0; if (issp) for (int i=1;i<=n;i++) ans=max(ans,(a[i]-1)/b[i]+1); else { issp=1; for (int i=1;i<=n;i++) if (a[i]!=p[i]) {issp=0;break;} if (issp) { ans=1; for (int i=1;i<=n;i++) if (b[i]%p[i]) b[i]%=p[i],ans=lcm(ans,p[i]/gcd(b[i],p[i])); } else { for (int i=1;i<=n;i++) if (b[i]%p[i]==0&&a[i]!=b[i]||a[i]%gcd(b[i],p[i])) {ans=-1;break;} else { b[i]%=p[i]; int x=gcd(b[i],p[i]); a[i]/=x,b[i]/=x,p[i]/=x; } if (~ans) { ll tmp;exgcd(b[1],p[1],ans,tmp);ans=(ans%p[1]+p[1])%p[1];ans=ksc(ans,a[1],p[1]); for (int i=2;i<=n;i++) { ll A=ksc(b[i],p[i-1],p[i]),B=(a[i]-ksc(b[i],ans,p[i])+p[i])%p[i]; ll x=gcd(p[i],p[i-1]);if (B%x) {ans=-1;break;} A/=x,B/=x,p[i]/=x; ll k;exgcd(A,p[i],k,tmp);k=(k%p[i]+p[i])%p[i];k=ksc(k,B,p[i]); p[i]*=p[i-1];ans=(ksc(k,p[i-1],p[i])+ans)%p[i]; } } } } printf(LL,ans); } return 0; }