Luogu P4774 [NOI2018]屠龙勇士

题面

题面和数据范围建议看原题。

题解

注意到每一次打龙的时候选择的剑都是唯一固定的,而且注意到同一攻击力的剑可以有多把,所以可以用 multiset 来维护一下。

所以现在打每一条龙相当于一个方程 \(atk_ix+p_iy=a_i\),移项得到 \(atk_ix\equiv a_i\pmod{a_i}\),直接使用 exCRT 即可。

这里我的代码是边打龙边合并方程,其实也可以确定下来剑之后逐一合并方程,long longlong long 可以直接龟速乘。

判断无解的情况比较麻烦,建议对代码看。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll MAXN=1e5+51;
ll test,n,m,xx,yy,kk,mx,c,g;
ll x[MAXN],y[MAXN],p[MAXN];
multiset<ll>st;
multiset<ll>::iterator it;
inline ll read()
{
    register ll num=0,neg=1;
    register char ch=getchar();
    while(!isdigit(ch)&&ch!='-')
    {
        ch=getchar();
    }
    if(ch=='-')
    {
        neg=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        num=(num<<3)+(num<<1)+(ch-'0');
        ch=getchar();
    }
    return num*neg;
} 
inline void exgcd(ll x,ll y,ll &xx,ll &yy)
{
    ll t;
    if(!y)
    {
        return (void)(xx=1,yy=0,g=x);
    }
    exgcd(y,x%y,xx,yy),t=xx,xx=yy,yy=t-x/y*yy;
}
inline ll mul(ll x,ll y,ll md)
{
    ll res=0;
    while(y)
    {
        if(y&1)
        {
            res=(res+x)%md;
        }
        x=(x<<1)%md,y>>=1;
    }
    return res;
}
inline void solve()
{
    n=read(),m=read();
    for(register int i=1;i<=n;i++)
    {
        x[i]=read();    
    }
    for(register int i=1;i<=n;i++)
    {
        p[i]=read();
    }
    for(register int i=1;i<=n;i++)
    {
        y[i]=read();
    }
    st.clear();
    for(register int i=1;i<=m;i++)
    {
        st.insert(read());
    }
    mx=c=0,m=1;
    for(register int i=1;i<=n;i++)
    {
        it=st.upper_bound(x[i]),it!=st.begin()?--it:it,kk=*it,st.erase(it);
        st.insert(y[i]),mx=max(mx,(x[i]-1)/kk+1),kk%=p[i],x[i]%=p[i];
        if(!kk&&x[i])
        {
            return (void)puts("-1");
        }
        if(!kk&&!x[i])
        {
            continue;
        }
        exgcd(kk,p[i],xx,yy);
        if(x[i]%g)
        {
            return (void)puts("-1");
        }
        p[i]/=g,x[i]=mul(x[i]/g,(xx%p[i]+p[i])%p[i],p[i]),exgcd(m,p[i],xx,yy);
        if((x[i]-c)%g)
        {
            return (void)puts("-1");
        }
        m=m/g*p[i],c=(c+mul(mul(m/p[i],((x[i]-c)%m+m)%m,m),(xx%m+m)%m,m))%m;
    }
    printf("%lld\n",c>=mx?c:c+m*((mx-c-1)/m+1));
}
int main()
{
    test=read();
    for(register int i=0;i<test;i++)
    {
        solve();
    }
}
posted @ 2020-08-12 11:20  Karry5307  阅读(132)  评论(0编辑  收藏  举报