洛谷P4774 [NOI2018]屠龙勇士

题目大意:

这个题面和数据范围不太好粘,自己看吧……

首先我们应该可以看出这是一道\(excrt\)题目

至于剑这个限制其实很\(naive\),用\(multiset\)存一下就好了

根据题意我们可以列出方程组

\[\begin{cases}d_1x\equiv a_1 (mod\ p_1)\\d_2x\equiv a_2 (mod\ p_2)\\……\\d_nx\equiv a_n (mod\ p_n)\end{cases}\]

其中\(d_i\)为剑攻击力,\(x\)为攻击次数,\(a_i\)为龙龙的血量,\(p_i\)为回复能力

毒瘤

但是我们好像有\(a_i>p_i\)的情况……根据题目我们好像不能直接模掉……

然而我们翻过题解之后发现可能存在\(a_i>p_i\)时,全部满足\(p_i=1\)那么我们大力判断掉就好了

具体方法:

\[ans=max\{ \lceil\frac{d_i}{a_i}\rceil \}\]

通解

先考虑\(d_ix\equiv a_i (mod\ p_i)\)好像和一般的\(crt\)方程不太一样,化简一下

\[x*d_i+y*p_i=- a_i\]

\(exgcd\)求出一组\(x_t,y_t\)

由于\(ecgcd\)通解为\(x=x_t+k*\frac{b}{gcd(a,b)}\),得到\(x=x_t+k*\frac{p_i}{gcd(p_i,d_i)}\)

\(\frac{p_i}{gcd(p_i,d_i)}\)取模,得到

\(x\equiv x_t (mod\ \frac{p_i}{gcd(p_i,d_i)})\)

然后大力\(excrt\)

注意

我们感性理解一下可以得出\(x\ge (maxn=max\{\lceil\frac{a_i}{d_i}\rceil\})\),如果最后答案小于这个数,应该补上

推出来是\(ret=ret+m*\lceil\frac{maxn-ret}{m}\rceil\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define eps (1e-8)
    inline int read()
    {
        int x=0;char ch,f=1;
        for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        if(ch=='-') f=0,ch=getchar();
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    const int N=1e5+10;
    int haku;
    int n,m;
    int a[N],p[N],sword[N];
    inline void exgcd(int &x,int &y,int &g,int a,int b)
    {
        if(!b){x=1,y=0,g=a;return;}
        exgcd(y,x,g,b,a%b);
        y-=a/b*x;
    }
    inline int slow(int x,int k,int p)
    {
        int ret=0;
        while(k)
        {
            if(k&1) ret=(ret+x)%p;
            x=(x+x)%p;
            k>>=1;
        }
        return ret;
    }
    multiset<int> q;
    multiset<int>::iterator it;
    inline int excrt()
    {
        int m=1,ret=0,maxn=0,x,y,g;
        for(int i=1;i<=n;++i)
        {
            it=q.upper_bound(a[i]);
            if(it!=q.begin()) --it;
            int k=*it;
            q.erase(it);
            q.insert(sword[i]);
            maxn=max(maxn,(a[i]-1)/k+1);
            k%=p[i],a[i]%=p[i];
            exgcd(x,y,g,k,p[i]);
            if(a[i]%g) return -1;
            p[i]/=g;
            a[i]=slow(a[i]/g,(x%p[i]+p[i])%p[i],p[i]);
            int c=((a[i]-ret)%p[i]+p[i])%p[i];
            exgcd(x,y,g,m,p[i]);
            if(c%g) return -1;
            x=slow(x,c/g,p[i]);
            ret+=x*m;
            m*=p[i]/g;
            ret%=m;
        }
        return ret>=maxn?ret:ret+m*((maxn-ret-1)/m+1);
    }
    inline void main()
    {
        haku=read();
        while(haku--)
        {
            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) sword[i]=read();
            for(int i=1;i<=m;++i) q.insert(read());
            printf("%lld\n",excrt());
            q.clear();
        }
    }
}
signed main()
{
    red::main();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/knife-rose/p/12058420.html