题意理解错了。。。

一把剑打一条龙,打了$x$次后如果龙不死,你就Game Over了。

显然,面对每条龙使用的剑是固定的,如果所有龙中有一条没打死你就挂了。

可以知道,可行的答案集合就是所有龙的可行集合的交集。

考虑当前面对第$i$条龙,若要打死它,$x$满足条件:$a_{i} - x * v_{i} + y * p_{i} = 0$,其中$a$是血量,$v$是攻击力,$p$是恢复力,$y$是某非负整数。

可以把它转化为同余式:$a_{i} \equiv x * v_{i} (mod \; p_{i})$。我们要找出满足该条件的$x$的最小正整数值。

通常情况下,只要先算$v_{i}$在$(mod \; p_{i})$意义下的逆元即可,但此时两者不互质,不一定存在逆元,根据数论某定理:$ a * c \equiv b * c (mod \; m) \Rightarrow a \equiv b (mod \; m / ( c , m ) $,我们先除去三者的$gcd$,再求逆元就可以了,如果此时仍然没有逆元,则无解。(这里有一个要注意的事情,当$p_{i}=1$的时候会出点问题,特判就可以了)

可以发现,$x$可以的取值是一个等差数列,我们需要把$n$个等差数列合并起来,取它们的交集。

假设我们即将合并的两个等差数列为$(a_{s}, d_{s}),(a_{i},d_{i})$,其中$a$为首项,$d$为公差。

合并后的公差比较好算:$lcm(d_{s},d_{i})$。主要考虑如何求第一个数同时出现在两个等差数列中了。

可以列出以下等式:$a_{s} + x * d_{s} = a_{i} + y * d_{i}$,其中$x, y$都是某个非负整数。

移项转化为同余式:$x * d_{s} \equiv a_{i} - a_{s} (mod \; d_{i})$,和刚刚的套路一样就可以解出$x$的值啦。

最后显然$a_{s}$就是我们想要的答案。(提示:由于中间答案过大,使用中精度存储,也可以用快速乘)

Update :

求同余式$x * a \equiv b (mod \; p)$的另一种思路,设$d = gcd(a, p)$,那有解当且仅当$d | b$。具体证明就是扩展欧几里得相关。

那该同余方程等价于$x * \frac{a}{d} \equiv \frac{b}{d} (mod \; \frac{p}{d})$。此时由于$\frac{b}{d}$一定与$\frac{p}{d}$互质,通过求逆元直接解出$x$即可。

$\bigodot$技巧&套路:

  • 基础数论,同余式$x * a \equiv b (mod \; p)$求解的技巧。
#include <cstdio>
#include <set> typedef long long LL;
const int N = ; int tc, n, m;
LL ai[N], di[N], a[N], p[N], b[N], v[N];
std::multiset<LL> S; inline LL Mul(LL a, LL b, LL p) {
a %= p; b %= p;
LL a0 = a & , a1 = a >> ;
return (((a1 * b % p) << ) + a0 * b) % p;
}
LL Ex_gcd(LL a, LL b, LL &x, LL &y) {
if (b == ) return x = , y = , a;
LL g = Ex_gcd(b, a % b, y, x);
y -= a / b * x;
return g;
} inline LL Get(LL x, LL re = ) {
auto it = S.upper_bound(x);
if (it != S.begin()) --it;
re = *it; S.erase(it);
return re;
} int main() {
scanf("%d", &tc);
for (; tc; --tc) {
S.clear();
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) scanf("%lld", &a[i]);
for (int i = ; i <= n; ++i) scanf("%lld", &p[i]);
for (int i = ; i <= n; ++i) scanf("%lld", &b[i]);
for (int i = ; i <= m; ++i) scanf("%lld", &v[i]), S.insert(v[i]); LL as = , ps = ;
for (int i = ; i <= n; ++i) {
LL vi = Get(a[i]), x, y, ai, pi;
LL d = Ex_gcd(vi, p[i], x, y);
if (a[i] % d != ) {
as = -; break;
}
x = (x % (p[i] / d) + p[i] / d) % (p[i] / d);
ai = Mul(a[i] / d, x, p[i] / d);
pi = p[i] / d;
if (p[i] == ) ai = a[i] / vi + (bool)(a[i] % vi);
S.insert(b[i]);
if (pi == ) {
if (as < ai) {
LL bl = (ai - as) / ps + (bool)((ai - as) % ps);
as = as + bl * ps;
}
continue;
}
LL dir = ((ai - as) % pi + pi) % pi;
d = Ex_gcd(ps, pi, x, y);
if (dir % d != ) {
as = -; break;
}
x = (x % (pi / d) + pi / d) % (pi / d);
LL nx = Mul(dir / d, x, pi / d);
as = as + nx * ps;
ps = ps / d * pi;
} printf("%lld\n", as);
} return ;
}

【NOI 2018】屠龙勇士(扩欧)的更多相关文章

  1. [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士

    [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...

  2. 洛谷P4774 [NOI2018]屠龙勇士 [扩欧,中国剩余定理]

    传送门 思路 首先可以发现打每条龙的攻击值显然是可以提前算出来的,拿multiset模拟一下即可. 一般情况 可以搞出这么一些式子: \[ atk_i\times x=a_i(\text{mod}\ ...

  3. NOI 2018 屠龙勇士 (拓展中国剩余定理excrt+拓展欧几里得exgcd)

    题目大意:略 真是一波三折的一道国赛题,先学了中国剩余定理,勉强看懂了模板然后写的这道题 把取出的宝剑攻击力设为T,可得Ti*x=ai(mod pi),这显然是ax=c(mod b)的形式 这部分用e ...

  4. NOI 2018网络同步赛(游记?)

    刚中考完那段时间比较无聊,报名了一个同步赛,报完名才发现成绩单是要挂到网上的,而且因为报的早给了一个很靠前的考号...那布星啊,赶紧学点东西,于是在一周内学了网络流,Treap以及一些数论. Day1 ...

  5. 洛谷 P4774 [NOI2018] 屠龙勇士

    链接:P4774 前言: 交了18遍最后发现是多组数据没清空/ll 题意: 其实就是个扩中. 分析过程: 首先发现根据题目描述的选择剑的方式,每条龙对应的剑都是固定的,有查询前驱,后继(在该数不存在前 ...

  6. NOI2018屠龙勇士(扩展CRT + splay(multiset))

    QWQ 一到假期就颓废 哎 今年新鲜出炉的NOI题,QwQ同步赛的时候写的,后来交了一发洛谷,竟然过了 首先 根据题目,我们很容易得到,假设对应每一条龙的剑的攻击力是\(atk\)的话 \[a_i-x ...

  7. 【POJ】2115 C Looooops(扩欧)

    Description A Compiler Mystery: We are given a C-language style for loop of type for (variable = A; ...

  8. BZOJ5418[Noi2018]屠龙勇士——exgcd+扩展CRT+set

    题目链接: [Noi2018]屠龙勇士 题目大意:有$n$条龙和初始$m$个武器,每个武器有一个攻击力$t_{i}$,每条龙有一个初始血量$a_{i}$和一个回复值$p_{i}$(即只要血量为负数就一 ...

  9. 「NOI2018」屠龙勇士(EXCRT)

    「NOI2018」屠龙勇士(EXCRT) 终于把传说中 \(NOI2018D2\) 的签到题写掉了... 开始我还没读懂题目...而且这题细节巨麻烦...(可能对我而言) 首先我们要转换一下,每次的 ...

  10. LOJ #2721. 「NOI2018」屠龙勇士(set + exgcd)

    题意 LOJ #2721. 「NOI2018」屠龙勇士 题解 首先假设每条龙都可以打死,每次拿到的剑攻击力为 \(ATK\) . 这个需要支持每次插入一个数,查找比一个 \(\le\) 数最大的数(或 ...

随机推荐

  1. RabbitMQ入门:路由(Routing)

    在上一篇博客<RabbitMQ入门:发布/订阅(Publish/Subscribe)>中,我们认识了fanout类型的exchange,它是一种通过广播方式发送消息的路由器,所有和exch ...

  2. Window10家庭版启动hyper-v虚拟机组件

    在安装docker的时候发现如果直接使用docker for windows,对系统的要求是window10专业版或企业版,家庭版本身没有hyper-v,不能支持 虚拟化.但是后来我在搜索过程中发现, ...

  3. tensorflow-gpu在win10下的安装

    参考:https://blog.csdn.net/gyp2448565528/article/details/79451212 按照原博主的方法在自己的机器上会有一点小错误,下面的方法略有不同 环境: ...

  4. Netty源码分析第4章(pipeline)---->第1节: pipeline的创建

    Netty源码分析第四章: pipeline 概述: pipeline, 顾名思义, 就是管道的意思, 在netty中, 事件在pipeline中传输, 用户可以中断事件, 添加自己的事件处理逻辑, ...

  5. 如何批量删除QQ浏览器指定历史记录和导出指定的历史记录

    QQ浏览器的历史记录只有清空历史记录和删除选中项两个功能.有时我不想删除所有的历史记录,只是想删除指定的历史记录保留对自己有用的历史记录,方便自己以后查找.但是删除选中项功能只能一项一项的选择,才能批 ...

  6. asp.net core如何修改程序监听的端口

    asp.net core 默认监听的5000和5001端口,要修改为其他端口有几种方法. 1.硬编码.优点是直观,缺点是每次修改端口都得重新编译程序. public class Program { p ...

  7. Spring Cloud限流思路及解决方案

    转自: http://blog.csdn.net/zl1zl2zl3/article/details/78683855 在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Clo ...

  8. Daily Scrum (2015/11/2)

    今日我们完成了博客作业的发布,并且也完成了服务器的配置. 成员 今日工作 时间 明日工作 符美潇 两篇文档的修善和数据库的搭建. 2h 完成数据库搭建,并能爬取数据提供给第二小组使用 潘礼鹏 编写两篇 ...

  9. springmvc 映射重复

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springfr ...

  10. ubuntu下安装matlab2015b

    ========= 安装过程 1.下载MATLAB2015b破解版 操作系统:Ubuntu 16.04 LTS 程序文件:Matlab2015b-glnxa64破解版 解压提取文件:在ubuntu系统 ...