https://www.lydsy.com/JudgeOnline/problem.php?id=5418
小D 最近在网上发现了一款小游戏。游戏的规则如下:
游戏的目标是按照编号1→n1 \rightarrow n1→n 顺序杀掉n条巨龙,每条巨龙拥有一个初始的生命值ai。同时每条巨龙拥有恢复能力,当其使用恢复能力时,它的生命值就会每次增加 pi ,直至生命值非负。只有在攻击结束后且当生命值恰好为 0 时它才会死去。
游戏开始时玩家拥有m 把攻击力已知的剑,每次面对巨龙时,玩家只能选择一 把剑,当杀死巨龙后这把剑就会消失,但作为奖励,玩家会获得全新的一把剑。 小D 觉得这款游戏十分无聊,但最快通关的玩家可以获得ION2018 的参赛资格, 于是小D 决定写一个笨笨的机器人帮她通关这款游戏,她写的机器人遵循以下规则:
每次面对巨龙时,机器人会选择当前拥有的,攻击力不高于巨龙初始生命值中攻击力最大的一把剑作为武器。如果没有这样的剑,则选择攻击力最低的一把剑作为武器。
机器人面对每条巨龙,它都会使用上一步中选择的剑攻击巨龙固定的x 次,使巨龙的生命值减少x×ATK。
之后,巨龙会不断使用恢复能力,每次恢复pi 生命值。若在使用恢复能力前或某一次恢复后其生命值为0,则巨龙死亡,玩家通过本关。
那么显然机器人的攻击次数是决定能否最快通关这款游戏的关键。小 D 现在得知了每条巨龙的所有属性,她想考考你,你知道应该将机器人的攻击次数x设置为多少,才能用最少的攻击次数通关游戏吗?
当然如果无论设置成多少都无法通关游戏,输出−1 即可。
输入格式:
从文件dragon.in 中读入数据。
第一行一个整数T ,代表数据组数。
接下来T 组数据,每组数据包含5行。
每组数据的第一行包含两个整数,n和m,代表巨龙的数量和初始剑的数量;
接下来一行包含n个正整数,第i个数表示第i条巨龙的初始生命值ai;
接下来一行包含n个正整数,第i个数表示第i条巨龙的恢复能力pi ;
接下来一行包含n个正整数,第i个数表示杀死第i 条巨龙后奖励的剑的攻击力;
接下来一行包含m个正整数,表示初始拥有的m把剑的攻击力。
输出格式:
输出到文件dragon.out 中。 一共T行。
第i 行一个整数,表示对于第i 组数据,能够使得机器人通关游戏的最小攻击次数x ,如果答案不存在,输出−1。
首先鸣谢ysy20021208帮助我踩坑,我才AC此题。
一眼扩展中国剩余定理
Pi × y+life=X×ATK
ATK×X ≡life(mod Pi)
板子题,解决!
纯属瞎扯!
国赛怎么可能这么水,即使是T1
EXCRT使用是有限制的,那就是X的系数必须为1,而现在的X系数为ATK。
这个ATK有可能在mod Pi的情况下有可能根本没有逆元,直接除更是不可以。
我们求解如何消去ATK?
使用exgcd算法求解一般的不定方程,解出特解,从而算出通解。
X×ATK+Pi?y=life?
用exgcd求出两个特解Sx和Sy
x=Sx+k× (Pi/gcd(ATK?,Pi?))
两边同时取模
x≡Sx(mod Pi /gcd(ATK?,Pi?) ??)
之后EX中国剩余定理出场与前面的合并解决。
解决了吗?
没有。
如果所有的Pi=Ai的话我们解同余方程的结果将会是0.但显然不对,应该直接求出杀死每条龙所需的刀数然后所有刀数求一个lcm即可。解方程的时候要扔掉。还有就是ATK是Pi的倍数是永远杀不掉龙的。
我们在确定是哪把刀时,要开一个multiset和一个桶,这是最关键的。
最后放代码
#include<cstdio>
#include<set>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 1000001
typedef long long ll;
multiset <ll> s;
ll m[N];
ll a[N];
ll life[N];
ll p[N];
ll gg[N];
bool flag;
ll t[N];
ll boom[N];
ll T,n,K;
ll maxn;
ll pow(ll x,ll y,ll mod)
{
ll ans=0;
while(y)
{
if(y&1)
ans=(ans+x)%mod;
x=(x+x)%mod;
y/=2;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(!b)
{
x=1;
y=0;
return a;
}
ll gcd=exgcd(b,a%b,x,y);
ll tmp=x;
x=y;
y=tmp-a/b*y;
return gcd;
}
ll find(ll num)
{
multiset <ll> ::iterator here=s.lower_bound(num);
if(here==s.end())
{
here--;
return -*here;
}
else
return -*here;
}
void in()
{
for(int i=1;i<=n;i++)
{
t[i]=find(-life[i]);
s.insert(-gg[i]);
boom[gg[i]]++;
if((--boom[t[i]])==0)
s.erase(-t[i]);
}
for(int i=1;i<=n;i++)
maxn=max(maxn,(life[i]%t[i])?(life[i]/t[i]+1):(life[i]/t[i]));
}
void is()
{
for(int i=1;i<=n;i++)
{
ll x,y;
ll gcd=exgcd(t[i],p[i],x,y);
if(life[i]%gcd)
{
flag=1;
return ;
}
x=pow(x,(life[i]/gcd),(p[i]/gcd));
a[i]=x;
m[i]=p[i]/gcd;
}
}
void init()
{
s.clear();
flag=0;
ll x;
maxn=0;
memset(boom,0,sizeof(boom));
memset(m,0,sizeof(m));
memset(a,0,sizeof(a));
scanf("%lld%lld",&n,&K);
for(int i=1;i<=n;i++)
scanf("%lld",&life[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&p[i]);
for(int i=1;i<=n;i++)
scanf("%lld",&gg[i]);
for(int i=1;i<=K;i++)
{
scanf("%lld",&x);
boom[x]++;
s.insert(-x);
}
in();
is();
}
ll China()
{
if(flag)
return -1;
ll M=m[1],olda=a[1];
for(int i=2;i<=n;i++)
{
ll A=M,B=m[i],d=((a[i]-olda)%B+B)%B,x,y;
ll gcd=exgcd(A,B,x,y);
if(d%gcd)
return -1;
x=pow(x,d/gcd,B/gcd);
M*=B/gcd;
olda=(olda+x*A)%M;
}
if(olda<maxn)
olda=olda+M*(((maxn-olda)%M)?((maxn-olda)/M+1):((maxn-olda)/M));
else if(olda>maxn)
olda=olda-M*((-maxn+olda)/M);
return olda;
}
int main()
{
scanf("%lld",&T);
while(T--)
{
init();
printf("%lld\n",China());
}
return 0;
}
原网站地址
https://www.cnblogs.com/342zhuyongqi/
原文:https://www.cnblogs.com/342zhuyongqi/p/9860902.html