• NOI2018/LuoGu P4774屠龙勇士


    本蒟蒻终于屠龙成功!!

    作为一个我的世界的资深玩家,对屠龙有着无比的信仰和热情!!

    首先吐槽一下这只信息龙,它变成负HP后居然不会死,只有他自己回血回到了0HP才算死23333

    来我们来看看题意描述,国赛的题意描述略长

    这道题其实没有那么的可怕,当时我写完excrt就有学长推荐我来写

    题目描述

    小 D 最近在网上发现了一款小游戏。游戏的规则如下: • 游戏的目标是按照编号 1~n 顺序杀掉 n 条巨龙,每条巨龙拥有一个初始的生命 值 a i 。同时每条巨龙拥有恢复能力,当其使用恢复能力时,它的生命值就会每 次增加 p i ,直至生命值非负。只有在 . 攻 . 击 . 结 . 束 . 后且当生命值 . 恰 . 好为 0 时它才会 死去。 • 游戏开始时玩家拥有 m 把攻击力已知的剑,每次面对巨龙时,玩家只能选择一把剑,当杀死巨龙后这把剑就会消失,但作为奖励,玩家会获得全新的一把剑。小 D 觉得这款游戏十分无聊,但最快通关的玩家可以获得 ION2018 的参赛资格,于是小 D 决定写一个笨笨的机器人帮她通关这款游戏,她写的机器人遵循以下规则:• 每次面对巨龙时,机器人会选择当前拥有的,攻击力不高于巨龙初始生命值中.攻.击.力.最.大的一把剑作为武器。如果没有这样的剑,则选择..击.力.最.低的一把剑作为武器。• 机器人面对每条巨龙,它都会使用上一步中选择的剑攻击巨龙.固.定.的 x 次,使巨龙的生命值减少 x × ATK 。• 之后,巨龙会不断使用恢复能力,每次恢复 p i 生命值。若在使用恢复能力前或某一次恢复后其生命值为 0 ,则巨龙死亡,玩家通过本关。那么显然机器人的.攻.击.次.数是决定能否最快通关这款游戏的关键。小 D 现在得知 了每条巨龙的所有属性,她想考考你,你知道应该将机器人的攻击次数 x 设置为多少,才能用最少的攻击次数通关游戏吗?当然如果无论设置成多少都无法通关游戏,输出-1 即可。

    输入格式

    从文件 dragon.in 中读入数据。 第一行一个整数 T ,代表数据组数。 接下来 T 组数据,每组数据包含 5 行。 • 每组数据的第一行包含两个整数,n 和 m ,代表巨龙的数量和初始剑的数量; • 接下来一行包含 n 个正整数,第 i 个数表示第 i 条巨龙的初始生命值 a i ; • 接下来一行包含 n 个正整数,第 i 个数表示第 i 条巨龙的恢复能力 p i ; • 接下来一行包含 n 个正整数,第 i 个数表示杀死第 i 条巨龙后奖励的剑的攻击 力; • 接下来一行包含 m 个正整数,表示初始拥有的 m 把剑的攻击力。

    输出格式

    输出到文件 dragon.out 中。 一共 T 行。 第 i 行一个整数,表示对于第 i 组数据,能够使得机器人通关游戏的最小攻击次数 x ,如果答案不存在,输出-1。

    样例一

    input

    2
    3 3
    3 5 7
    4 6 10
    7 3 9
    1 9 1000
    3 2
    3 5 6
    4 8 7
    1 1 1
    1 1
    

    output

    59
    -1
    

    样例 1 解释

    第一组数据:
    • 开始时拥有的剑的攻击力为 {1,9,10},第 1 条龙生命值为 3,故选择攻击力为 1的剑,攻击 59 次,造成 59 点伤害,此时龙的生命值为-56,恢复 14 次后生命值
    恰好为 0,死亡。• 攻击力为 1 的剑消失,拾取一把攻击力为 7 的剑,此时拥有的剑的攻击力为{7,9,10},第 2 条龙生命值为 5,故选择攻击力为 7 的剑,攻击 59 次,造成 413点伤害,此时龙的生命值为-408,恢复 68 次后生命值恰好为 0,死亡。• 此时拥有的剑的攻击力为 {3,9,10},第 3 条龙生命值为 7,故选择攻击力为 3 的
    剑,攻击 59 次,造成 177 点伤害,此时龙的生命值为-170,恢复 17 次后生命值恰好为 0,死亡。
    • 没有比 59 次更少的通关方法,故答案为 59。
    第二组数据:
    • 不存在既能杀死第一条龙又能杀死第二条龙的方法,故无法通关,输出-1。
    

    子任务

    特性 1 是指:对于任意的 i,a i ≤ p i 。
    特性 2 是指:LCM(p i ) ≤ 10 6 即所有 p i 的最小公倍数不大于 10 6 。
    对于所有的测试点,T ≤ 5 ,所有武器的攻击力 ≤ 10 6 ,所有 p i 的.最.小.公.倍.数≤ 10 12 。
    

    你所用到的中间结果可能很大,注意保存中间结果的变量类型。

    限制与约定

    时间限制2s2s

    空间限制512MB

    好了我们来看看这道题的思路是什么

    首先题要读懂!!我就是读错了题导致WA了三个点(数据好水居然只WA了三个)

    通过题干可得(heal是回复,atk是攻击)

    ATK*x = hp + heal*y

    然后呢我们mod一个heal

    ATK*x = hp + heal*y(% heal})

    $AT{K_i}*x = h{p_i}(\% hea{l_i})$

    就很明了了,是一个ex中国剩余定理,因为x是固定的,取模数不一定是质数

    现在的问题是x前面有一个讨厌的系数,它应该怎么弄掉,对,把它除到右面就好了

    $x = h{p_i}*ATK_i^{ - 1}(\% hea{l_i})$

    很明显就是求一个ATK关于heali的逆元(注意先约分再求逆元,除了零以外,所有两个互质的数之间都存在逆元)

    做题的好习惯是看数据范围,看到前几组数据了吗,显然攻击力恢复力全是1,excrt是过不了的,那也很简单,只要把它砍成刚变成负值就好了,也很简单

    但是看到后面的数据范围十分庞大,显然在选剑的时候回TLE,那么就需要一些数据结构,用multiset就好(不用set因为有重复元素)

    这里用到了一个函数叫upperbound,它会返回最后一个大于等于它的数的迭代器,再- -就是选的剑,这个是set的存储特点,注意每次都clear()一下就OK

    上代码!

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<set>
      5 using namespace std;
      6 typedef long long ll;
      7 #define N 100011
      8 #define M 100011
      9 #define rg register
     10 ll T,n,m,x,y;bool fl=1;
     11 ll hp[N],reward[N],heal[N],sword,r[N],a[N];
     12 multiset<ll>S;
     13 namespace ldy
     14 {
     15     ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
     16     ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
     17     ll ksc(ll a,ll b,ll mod)
     18     {
     19         ll fina=0,kk=1;
     20         if(a<0)a=-a,kk=-kk;
     21         if(b<0)b=-b,kk=-kk;
     22         while(b)
     23         {
     24             if(b%2)fina=(fina+a)%mod;
     25             b>>=1,a=(a+a)%mod;
     26         }
     27         return fina%mod*kk;
     28     }
     29     ll read()
     30     {
     31         ll f=1,x=0;
     32         char ss=getchar();
     33         while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
     34         while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
     35         return f*x;
     36     }
     37     void ex_gcd(ll a,ll b)
     38     {
     39         if(!b)x=1,y=0;
     40         else
     41         {
     42             ex_gcd(b,a%b);
     43             ll tt=x;x=y;y=tt-a/b*x;
     44         }
     45     }
     46     ll exgcd(ll a,ll b,ll c)
     47     {
     48         ll gc=gcd(a,b);
     49         if(c%gc)return -1;
     50         a/=gc,b/=gc,c/=gc;
     51         ex_gcd(a,b);
     52         return (ksc(x,c,b)+b)%b;
     53     }
     54 }
     55 using namespace ldy;
     56 void init()
     57 {
     58     for(rg int i=1;i<=n;i++)
     59     {
     60         multiset<ll>::iterator it =S.upper_bound(hp[i]);
     61         if(it!=S.begin())it--;
     62         ll atk=*it;
     63         ll gc=gcd(atk,heal[i]);
     64         atk/=gc,hp[i]/=gc,heal[i]/=gc;
     65         a[i]=heal[i],r[i]=ksc(hp[i],exgcd(atk,heal[i],1),heal[i]);
     66         S.erase(it),S.insert(reward[i]);
     67     }    
     68 }
     69 ll excrt()
     70 {
     71     for(int i=1;i<n;i++)
     72     {
     73         ll k0=exgcd(a[i],a[i+1],r[i+1]-r[i]);
     74         if(k0==-1)return -1;
     75         r[i+1]=a[i]*k0+r[i];
     76         a[i+1]=lcm(a[i],a[i+1]);
     77     }
     78     return exgcd(1,a[n],r[n]);
     79 }
     80 ll lie()
     81 {
     82     ll ans=-1;
     83     for(int i=1;i<=n;i++)
     84     {
     85         multiset<ll>::iterator it =S.upper_bound(hp[i]);
     86         if(it!=S.begin())it--;
     87         ll atk=*it;
     88         if(hp[i]%atk)ans=max(ans,hp[i]/atk+1);
     89         else ans=max(ans,hp[i]/atk);
     90         S.erase(it),S.insert(reward[i]);
     91     }
     92     return ans;
     93 }
     94 int main()
     95 {
     96     for(int tt=read();tt>0;tt--)
     97     {
     98         n=read(),m=read();fl=1;
     99         for(rg int i=1;i<=n;i++)hp[i]=read(); 
    100         for(rg int i=1;i<=n;i++){heal[i]=read();if(heal[i]!=1)fl=0;}
    101         for(rg int i=1;i<=n;i++)reward[i]=read();
    102         for(rg int i=1;i<=m;i++){sword=read();S.insert(sword);}
    103         if(fl)printf("%lld
    ",lie());
    104         else init(),printf("%lld
    ",excrt());
    105         S.clear();
    106     }                        
    107     return 0;
    108 }
  • 相关阅读:
    mysql的if 和 case when
    hive的日期和时间
    DVWA——XSS(Stored)(存储型跨站脚本)
    DVWA——XSS(Reflected)(反射型跨站脚本)
    DVWA——SQL Injection(Blind)(SQL盲注)
    转载一篇注入类型判断
    DVWA——SQL Injection(SQL注入)
    DVWA——Insecure CAPTCHA (不安全的验证码)
    DVWA——File Upload(文件上传)
    DVWA——File Inclusion(文件包含)
  • 原文地址:https://www.cnblogs.com/Qin-Wei-Kai/p/10096955.html
Copyright © 2020-2023  润新知