zoukankan      html  css  js  c++  java
  • [NOI2018]屠龙勇士

    题目描述

    小D 最近在网上发现了一款小游戏。游戏的规则如下:

    • 游戏的目标是按照编号1→n1 ightarrow n1n 顺序杀掉nnn 条巨龙,每条巨龙拥有一个初始的生命值aia_iai 。同时每条巨龙拥有恢复能力,当其使用恢复能力时,它的生命值就会每次增加 pip_ipi ,直至生命值非负。只有在攻击结束后且当生命值恰好000 时它才会死去。

    • 游戏开始时玩家拥有mmm 把攻击力已知的剑,每次面对巨龙时,玩家只能选择一 把剑,当杀死巨龙后这把剑就会消失,但作为奖励,玩家会获得全新的一把剑。 小D 觉得这款游戏十分无聊,但最快通关的玩家可以获得ION2018 的参赛资格, 于是小D 决定写一个笨笨的机器人帮她通关这款游戏,她写的机器人遵循以下规则:

    • 每次面对巨龙时,机器人会选择当前拥有的,攻击力不高于巨龙初始生命值中攻击力最大的一把剑作为武器。如果没有这样的剑,则选择攻击力最低的一把剑作为武器。

    • 机器人面对每条巨龙,它都会使用上一步中选择的剑攻击巨龙固定的xxx 次,使巨龙的生命值减少x×ATKx imes ATKx×ATK 。

    • 之后,巨龙会不断使用恢复能力,每次恢复pip_ipi 生命值。若在使用恢复能力前或某一次恢复后其生命值为000 ,则巨龙死亡,玩家通过本关。

    那么显然机器人的攻击次数是决定能否最快通关这款游戏的关键。小 D 现在得知了每条巨龙的所有属性,她想考考你,你知道应该将机器人的攻击次数xxx 设置为多少,才能用最少的攻击次数通关游戏吗?

    当然如果无论设置成多少都无法通关游戏,输出−1-11 即可。

    输入输出格式

    输入格式:

    从文件dragon.in 中读入数据。

    第一行一个整数T ,代表数据组数。

    接下来T 组数据,每组数据包含555 行。

    • 每组数据的第一行包含两个整数,nnn 和mmm ,代表巨龙的数量和初始剑的数量;

    • 接下来一行包含nnn 个正整数,第iii 个数表示第iii 条巨龙的初始生命值aia_iai ;

    • 接下来一行包含nnn 个正整数,第iii 个数表示第iii 条巨龙的恢复能力pip_ipi ;

    • 接下来一行包含nnn 个正整数,第iii 个数表示杀死第iii 条巨龙后奖励的剑的攻击力;

    • 接下来一行包含mmm 个正整数,表示初始拥有的mmm 把剑的攻击力。

    输出格式:

    输出到文件dragon.out 中。 一共TTT 行。

    iii 行一个整数,表示对于第iii 组数据,能够使得机器人通关游戏的最小攻击次数xxx ,如果答案不存在,输出−1-11。

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    拓中,带系数的拓中。

    将每个式子化成 x ≡ a (mod p) 的形式,然后拓中直接求。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define inf 10000000000001ll
    #define N 200050
    inline ll rd()
    {
        ll f=1,c=0;char ch = getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=(c<<3)+(c<<1)+ch-'0';ch=getchar();}
        return f*c;
    }
    ll T,n,m;
    struct sword
    {
        int ch[N][2],fa[N],rt,tot,rep[N];
        ll w[N];
        void rotate(int x)
        {
            int y = fa[x],z = fa[y],k = (ch[y][1]==x);
            ch[y][k] = ch[x][!k],fa[ch[x][!k]]=y;
            ch[x][!k] = y,fa[y] = x;
            ch[z][ch[z][1]==y] = x,fa[x] = z;
        }
        void splay(int x,int goal)
        {
            while(fa[x]!=goal)
            {
                int y = fa[x],z = fa[y];
                if(z!=goal)
                    ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
                rotate(x);
            }
            if(!goal)rt=x;
        }
        int findr(ll x)
        {
            int ret = rt,u = rt;
            while(u){if(w[u]>x)ret=u;u=ch[u][w[u]<=x];}
            splay(ret,0);
            return ret;
        }
        int findl(ll x)
        {
            int ret = rt,u = rt;
            while(u){if(w[u]<x)ret=u;u=ch[u][w[u]<x];}
            splay(ret,0);
            return ret;
        }
        ll find(ll x)
        {
            int ret = rt,u = rt;
            while(u){if(w[u]<x)ret=u;if(w[u]==x)return x;u=ch[u][w[u]<x];}
            splay(ret,0);
            return w[ret];
        }
        void insert(ll k)
        {
            int u = rt,f=rt;
            while(u&&w[f]!=k)f=u,u=ch[u][w[u]<k];
            if(w[f]==k)
            {
                rep[f]++;
                return ;
            }
            u=++tot;
            if(f)ch[f][k>w[f]]=u;
            fa[u]=f,rep[u]=1,w[u]=k;
            ch[u][0]=ch[u][1]=0;
            splay(u,0);
        }
        void erase(ll k)
        {
            int r = findr(k),l = findl(k);
            splay(l,0);splay(r,l);
            if(rep[ch[r][0]]>1)
            {
                rep[ch[r][0]]--;
            }else fa[ch[r][0]]=0,ch[r][0]=0;
        }
        void clear()
        {
            rt=tot=0;
        }
    }sw;
    ll ai[N],pi[N],wi[N],mx;
    void init()
    {
        sw.clear();
        sw.insert(inf);
        sw.insert(-1);
        mx=-1;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
        if(!b)
        {
            x=1,y=0;
            return a;
        }
        ll ret = exgcd(b,a%b,y,x);
        y-=a/b*x;
        return ret;
    }
    ll mul(ll x,ll y,ll mod)
    {
        ll ret = 0;
        while(y)
        {
            if(y&1)ret=(ret+x)%mod;
            x=(x+x)%mod;
            y>>=1;
        }
        return ret;
    }
    ll zhx[N],jdr[N];
    int fkzhx()
    {
        ll x,y,wk;
        for(int i=1;i<=n;i++)
        {
            wk = sw.find(ai[i]);if(wk<0)wk=sw.w[sw.findr(ai[i])];sw.erase(wk);sw.insert(wi[i]);
            ll gcd = exgcd(wk,pi[i],x,y);
            if(ai[i]%gcd)return 0;
            jdr[i] = pi[i]/gcd;
            x = mul(x,ai[i]/gcd,jdr[i]);
            x = (x%jdr[i]+jdr[i])%jdr[i];
            zhx[i] = x;
            mx=max(mx,ai[i]/wk);
        }
        return 1;
    }
    ll excrt()
    {
        ll A = 0,P = 1,x,y;
        for(int i=1;i<=n;i++)
        {
            ll a = P , b = jdr[i] , c = ((zhx[i]-A)%b+b)%b;//取模,不然会死 
            ll gcd = exgcd(a,b,x,y);
            if(c%gcd)return -1;
            P *= jdr[i]/gcd;
            x = (x%P+P)%P,c = (c%P+P)%P;
            x = mul(x,c,P);
            A = (A + mul(P/jdr[i],x,P))%P;
        }
        A = (A%P+P)%P;
        if(A<mx)return A+((mx-A)/P+(mx%A!=0))*P;//不加特判会挂 
        return A;
    }
    int main()
    {
        T = rd();
        while(T--)
        {
            init();
            n=rd(),m=rd();
            for(int i=1;i<=n;i++)
                ai[i]=rd();
            for(int i=1;i<=n;i++)
                pi[i]=rd();
            for(int i=1;i<=n;i++)
                wi[i]=rd();
            for(int i=1;i<=m;i++)
                sw.insert(rd());
            int fk = 1;
            for(int i=1;i<=n&&fk;i++)
                if(pi[i]!=1)
                    fk=0;
            if(fk)
            {
                ll ans = 0,wk;
                for(int i=1;i<=n;i++)
                {
                    wk = sw.find(ai[i]);if(wk<0)wk=sw.w[sw.findr(ai[i])];sw.erase(wk);sw.insert(wi[i]);
                    ans = max(ans,ai[i]/wk+(ai[i]%wk!=0));
                }
                printf("%lld
    ",ans);
            }else
            {
                int r = fkzhx();
                if(!r)printf("-1
    ");
                else printf("%lld
    ",excrt());
            }
        }
        return 0;
    }
  • 相关阅读:
    *三维数组的初始化及遍历三个for循环
    *二维数组的初始化
    用while判读循环语句1+1/2!+1/3!+...1/20!的和阶乘的计算方法 式:n!=n*(n-1)!
    求一组数组各个元素的和*
    *求一组数组各个元素的和*
    使用for循环输出杨辉三角-还是不懂得需要复习
    使用for循环输出空心的菱形的思路-还是没有办法理解
    Break用法再举例
    continue用来结束本次循环 break用来结束整个循环体
    LeetCode.1154-一年中的第几天(Day of the Year)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9734008.html
Copyright © 2011-2022 走看看