这是拓展crt的典型应用

在你开始做之前,我一定要告诉你一件事情:虽然这道题看着和拓展crt模板很像,但他俩是有巨大的区别的!不要直接把板子改吧改吧扔上去!

题目模型:求解模线性方程组

其中p1,p2...pn不一定互质

第一眼:拓展crt板子题!

第二眼:等等...好像不太对

第三眼:WTF!系数哪来的!

我们知道,拓展crt的模板只能解决x系数为1的情况,而系数不为1的是很难做的!

什么?直接乘逆元变成1?

逆元不存在呢?

我们稍微做一点推导:

首先,我们解一下方程

设这个方程的一个解是x0(这是可以使用拓展gcd求解的)

那么这个方程的通解应该是,k∈Z

那么这个通解等价于方程的解

发现什么了吗?

是的!我们证明了方程与方程等价,这样就消掉了前面那个方程的系数!

所以,原方程组等价于这样:

这就很好了,我们使用正常的拓展crt解之即可

最后有几个细节问题:

①:对于ai>pi的情况,题目中给出的约束条件是pi=1,这样虽然拓展crt处理不了,但是我们可以应用特判过掉(p=1啊,多显然)

②:对于所有ai=pi的情况(即任一ai都=pi),只有当对应的攻击力是pi的倍数的时候才有解,否则无解,这个也要特判(有解也要特判,否则拓展crt解的结果会是0)

③:对于部分ai=pi的情况,如果对应攻击力不是pi的倍数则无解,但如果是pi的倍数,那么这个方程基本没用,可以替换成之类的形式

④:题目中运算很大,对于带取模的乘法需要快速加优化!同时所有数据类型建议使用long long以免挂掉

(求前驱那里本人使用的是treap,表示很好用)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define ll long long
#define ls tree[rt].lson
#define rs tree[rt].rson
#define INF 0x3f3f3f3f
using namespace std;
ll n,m;
ll a[];
ll b[];
ll life[];
ll acc[];
ll p[];
ll s[];
int cyt=;
int rot=;
struct Treap
{
int lson;
int rson;
int huge;
int same;
ll val;
int rank;
}tree[];
void update(int rt)
{
tree[rt].huge=tree[ls].huge+tree[rs].huge+tree[rt].same;
}
void lturn(int &rt)
{
int temp=rs;
rs=tree[rs].lson;
tree[temp].lson=rt;
tree[rt].huge=tree[temp].huge;
update(temp);
rt=temp;
}
void rturn(int &rt)
{
int temp=ls;
ls=tree[ls].rson;
tree[temp].rson=rt;
tree[rt].huge=tree[temp].huge;
update(temp);
rt=temp;
}
void ins(int &rt,ll v)
{
if(!rt)
{
rt=++cyt;
tree[rt].huge=;
tree[rt].same=;
tree[rt].val=v;
tree[rt].rank=rand();
return;
}
if(v==tree[rt].val)
{
tree[rt].huge++;
tree[rt].same++;
return;
}else if(tree[rt].val>v)
{
ins(ls,v);
if(tree[ls].rank<tree[rt].rank)
{
rturn(rt);
}
}else
{
ins(rs,v);
if(tree[rs].rank<tree[rt].rank)
{
lturn(rt);
}
}
}
void del(int &rt,ll v)
{
if(!rt)
{
return;
}
if(tree[rt].val==v)
{
if(tree[rt].same>)
{
tree[rt].huge--;
tree[rt].same--;
return;
}else if(ls*rs==)
{
rt=ls+rs;
return;
}else
{
if(tree[ls].rank<tree[rs].rank)
{
rturn(rt);
del(rt,v);
}else
{
lturn(rt);
del(rt,v);
}
}
}
tree[rt].huge--;
if(tree[rt].val>v)
{
del(ls,v);
}else
{
del(rs,v);
}
update(rt);
}
void query_pro(int rt,ll v,int typ)
{
if(!rt)
{
return;
}
if(tree[rt].val==v)
{
acc[typ]=v;
return;
}else if(tree[rt].val<v)
{
acc[typ]=tree[rt].val;
query_pro(rs,v,typ);
}else
{
query_pro(ls,v,typ);
}
}
int query_min(int rt)
{
if(ls&&tree[ls].val!=-INF)
{
return query_min(ls);
}else if(tree[rt].val!=-INF)
{
return tree[rt].val;
}else
{
return query_min(rs);
}
}
ll pow_add(ll x,ll y,ll mod)
{
ll ans=;
while(y)
{
if(y%)
{
ans+=x;
ans%=mod;
}
y/=;
x+=x;
x%=mod;
}
return ans;
}
ll gcd(ll x,ll y)
{
if(y==)
{
return x;
}
return gcd(y,x%y);
}
void ex_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==)
{
x=;
y=;
return;
}
ex_gcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-(a/b)*x;
}
bool makeit()
{
for(int i=;i<=n;i++)
{
if(acc[i]%p[i]==)
{
if(p[i]==life[i])
{
a[i]=;
b[i]=;
continue;
}else
{
printf("-1\n");
return ;
}
}
ll x,y;
ll r=gcd(acc[i],p[i]);
if(life[i]%r)
{
printf("-1\n");
exit();
}
acc[i]/=r;
ll temp=life[i]/r;
ll tt=p[i]/r;
ex_gcd(acc[i],tt,x,y);
x=(pow_add(x,temp,tt)+tt)%tt;
b[i]=x;
a[i]=tt;
}
return ;
}
ll ex_crt()
{
ll M0=a[];
ll ans=b[];
for(int i=;i<=n;i++)
{
ll r=gcd(M0,a[i]);
ll bb=((b[i]-ans)%a[i]+a[i])%a[i];
if(bb%r)
{
return -;
}
bb/=r;
ll M=M0/r;
ll aa=a[i]/r;
ll x,y;
ex_gcd(M,aa,x,y);
x=pow_add(x,bb,aa);
ans+=x*M0;
M0*=aa;
ans=(ans%M0+M0)%M0;
}
return (ans%M0+M0)%M0;
}
ll T;
int main()
{
scanf("%lld",&T);
while(T--)
{
memset(tree,,sizeof(tree));
rot=;
cyt=;
ins(rot,-INF);
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%lld",&life[i]);//龙的生命力
}
bool flag=,flag1=;
for(int i=;i<=n;i++)
{
scanf("%lld",&p[i]);//龙的恢复力
if(life[i]>p[i])
{
flag=;
}
if(life[i]!=p[i])
{
flag1=;
}
}
for(int i=;i<=n;i++)
{
scanf("%lld",&s[i]);
}
for(int i=;i<=m;i++)
{
ll x;
scanf("%lld",&x);
ins(rot,x);
}
for(int i=;i<=n;i++)
{
acc[i]=;
query_pro(rot,life[i],i);
if(acc[i]==-INF)
{
acc[i]=query_min(rot);
}
del(rot,acc[i]);
ins(rot,s[i]);
}
if(!flag1)
{
bool flag2=;
ll ans=;
for(int i=;i<=n;i++)
{
if(life[i]%acc[i]!=)
{
printf("-1\n");
flag2=;
}else
{
ll cd=gcd(ans,life[i]/acc[i]);
ans*=life[i]/acc[i]/cd;
}
}
if(!flag2)
{
printf("%lld\n",ans);
}
continue;
}
if(flag)
{
ll temp=;
for(int i=;i<=n;i++)
{
if(life[i]%acc[i]!=)
{
temp=max(temp,life[i]/acc[i]+);
}else
{
temp=max(temp,life[i]/acc[i]);
}
}
printf("%lld\n",temp);
continue;
}
if(makeit())
{
continue;
}
printf("%lld\n",ex_crt());
}
return ;
}

bzoj 5418的更多相关文章

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

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

  2. 【刷题】BZOJ 5418 [Noi2018]屠龙勇士

    www.lydsy.com/JudgeOnline/upload/noi2018day2.pdf Solution 将攻击的式子列出来,\(atk \times x-p \times y=a_i\) ...

  3. BZOJ 5418: [Noi2018]屠龙勇士 EXCRT+multiset

    题解:求解形如 $A[i]ans\equiv b[i](mod$ $p[i])$ 的 $x$ 的最小正整数解. 考虑只有一个等式,那么可以直接化成 $exgcd$ 的形式:$A[i]ans+p[i]y ...

  4. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  5. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  6. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  7. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  8. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

  9. 【sdoi2013】森林 BZOJ 3123

    Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...

随机推荐

  1. C - Boss Gym - 101473C (模拟)

    题目链接:https://cn.vjudge.net/contest/287775#problem/C 题目大意:给你n个人,然后m条关系,会有k次询问,每一次询问包括两种类型,第一种类型是交换两个人 ...

  2. [转] 解决Driver/library version mismatch

    跑模型 torch.cuda.is_available()返回 False nvidia-smi返回:Failed to initialize NVML: Driver/library version ...

  3. mvc5怎么给所有action都设置几个公用的ViewBag

    最近开发项目中遇到这样的问题,因为有多个同步的页面,所以需要在多个同步页面上有相同的值返回回来,经过一系列的思维,我们把思维整理出来. public ActionResult Index() { Vi ...

  4. 【ARTS】01_20_左耳听风-20190325~20190331

    zz## ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 ...

  5. Direct Shot Correspondence Matching

    一篇BMVC18的论文,关于semantic keypoints matching.dense matching的工作,感觉比纯patch matching有意思,记录一下. 1. 摘要 提出一种针对 ...

  6. MySQL中binlog参数:binlog_rows_query_log_events-记录具体的SQL【转】

    在使用RBR也就是行格式的时候,去解析binlog,需要逆向才能分析出对应的原始SQL是什么,而且,里面对应的是每一条具体行变更的内容.当然,你可以开启general log,但如果我们需要的只是记录 ...

  7. 单点登录SSO的原理及实现方式总结

      核心思想   用户信息的集中存储(全局Cooike.集中式Session.Json Web Token.Redis缓存服务器.自定义SSO服务器)   认证(Filter中执行)   登出(不同站 ...

  8. Stetho简化Android调试(二)

    Stetho简化Android调试(一) 一文中讲述了如何使用Stetho结合Chrome远程调试Android App. Stetho给我们调试带来很大的便利,效率显著提升的同时也产生一个问题:如果 ...

  9. PID控制器开发笔记之一:PID算法原理及基本实现

    在自动控制中,PID及其衍生出来的算法是应用最广的算法之一.各个做自动控制的厂家基本都有会实现这一经典算法.我们在做项目的过程中,也时常会遇到类似的需求,所以就想实现这一算法以适用于更多的应用场景. ...

  10. R-CNN,SPP-NET, Fast-R-CNN,Faster-R-CNN, YOLO, SSD系列

    就是想保存下来,没有其他用意 原博文:http://blog.csdn.net/qq_26898461/article/details/53467968 3. 空间定位与检测     参考信息< ...