NOI2018:屠龙勇士

题面

具体思路:发现对于每条巨龙,用的剑是一样的,那么可以用map先处理出来

然后对于每个龙就是一个一次同余方程,然后n条龙就是一个方程组,那么就是个CRT了

由于可能爆long long,要用龟速快速乘(考试时没想到结果爆成暴力分)

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=100010;
int T,n,m,a[N],p[N],atk[N],be[N],each[N],x,y,re[N],mod[N];
map<int,int> mp;
map<int,int>::iterator it;
int Mul(int a,int b,int md)
{
    int res=0;a=(a%md+md)%md,b=(b%md+md)%md;
    while(b)
    {
        if(b&1)res=(res+a)%md;
        b>>=1,a<<=1,a%=md;
    }
    return res;
}
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
int ex_gcd(int a,int b,int &x,int &y)
{
    int d=a;
    if(!b)x=1,y=0;else d=ex_gcd(b,a%b,y,x),y-=(a/b)*x;
    return d;
}
int MLE(int *r,int *mod,int n)
{
    int lm=0,lb=1;
    for (int i=0;i<n;i++)
    {
        int k1,k2;
        int d=ex_gcd(lb, mod[i],k1,k2);
        if ((lm-r[i])%d)return -1;
        lb=lb/d*mod[i];
        int z=Mul(k2,((lm-r[i])/d),lb);    
        lm=Mul(z,mod[i],lb)+r[i],lm=((lm%lb)+lb)%lb;    
    }
    if(lm)return lm;else return lb;
}
signed main()
{
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld%lld",&n,&m);mp.clear();int onlyone=1;
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        for(int i=1;i<=n;i++)scanf("%lld",&p[i]),onlyone&=p[i]==1;
        for(int i=1;i<=n;i++)scanf("%lld",&atk[i]);
        for(int i=1;i<=m;i++)scanf("%lld",&be[i]),mp[be[i]]++;
        
        for(int i=1;i<=n;i++)
        {
            it=mp.begin();
            if((*it).first>a[i])
            {
                (*it).second--;each[i]=(*it).first;
                if((*it).second==0)mp.erase(it);
            }else
            {
                it=mp.upper_bound(a[i]);it--;
                (*it).second--;each[i]=(*it).first;
                if((*it).second==0)mp.erase(it);
            }
            mp[atk[i]]++;
        }
        int ans=1;
        if(onlyone)
        {
            ans=0;
            for(int i=1;i<=n;i++)ans=max(ans,(a[i]/each[i])+((a[i]%each[i])>0));
            printf("%lld\n",ans);continue;
        }
        for(int i=1;i<=n;i++)
        {
            int g=gcd(each[i],p[i]);
            each[i]/=g,p[i]/=g;
            if(a[i]%g){ans=0;break;}
            a[i]/=g;
            ex_gcd(each[i],p[i],x,y);int inv=x;
            re[i]=Mul(inv,a[i],p[i]);mod[i]=p[i];if(mod[i]==1)re[i]=1;
        }
        if(ans==0){puts("-1");continue;}
        ans=MLE(re+1,mod+1,n);
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Orange-User/p/9364899.html
今日推荐