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;
}

猜你喜欢

转载自www.cnblogs.com/Gloid/p/10181105.html