bzoj 5418
这是拓展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的更多相关文章
- [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士
[LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...
- 【刷题】BZOJ 5418 [Noi2018]屠龙勇士
www.lydsy.com/JudgeOnline/upload/noi2018day2.pdf Solution 将攻击的式子列出来,\(atk \times x-p \times y=a_i\) ...
- BZOJ 5418: [Noi2018]屠龙勇士 EXCRT+multiset
题解:求解形如 $A[i]ans\equiv b[i](mod$ $p[i])$ 的 $x$ 的最小正整数解. 考虑只有一个等式,那么可以直接化成 $exgcd$ 的形式:$A[i]ans+p[i]y ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
- BZOJ 题目整理
bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
随机推荐
- 在Github和oschina上搭建自己的博客网站
在Github上搭建 - 参考链接 搭建一个免费的,无限流量的Blog----github Pages和Jekyll入门 GitHub + Jekyll 搭建并美化个人网站 用Jekyll搭建的Git ...
- react-踩坑记录——页面底部多出一倍高度的空白
挂载slider组件后页面底部多出一倍高度的空白,如下: slider组件内容⬇️: class Slider extends Component{ constructor(){ super(); } ...
- python - 获取win系统参数,发送/保存配置
import wmi import json c = wmi.WMI () msg = {} # 系统信息:系统版本,主机名,系统安装时间,系统位数,串口ID,总内存大小 system = ['Cap ...
- Django学习手册 - ORM 数据创建/表操作 汇总
ORM 查询的数据类型: QuerySet与惰性机制(可以看作是一个列表) 所谓惰性机制:表名.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它 ...
- 为什么HTTPS比HTTP安全,以及两者的优缺点
一.HTTPS简介 HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全:另一种就是确认网站的真实性. HTTP协议传输的数据都是未加密的,也就是明文的,因此使用HT ...
- 1173 - The Vindictive Coach
题目大意:n个不同身高的队员和教练的按照身高排成波浪形……每个人按照身高由低到高编号,其中第m个是教练,他必须在第一个,如果条件允许,排第二的要比m低,如果条件不允许,即其余人都比教练高,则要让差距尽 ...
- python第一天,简单输出及基本运算符
1.安装步骤网上很多详细的图文资料,这里就不一一赘述. 我的环境:win7 64bit +python-3.7.0b2 2.简单的输出(3.0之后和之前的版本略有不同) 1)打开控制台输入python ...
- [Docker]CentOS7通过rpm包安装Docker
前几天写过一篇文章:[Docker]CentOS7下Docker安装教程,直接使用yum命令下载Docker即可.但是前提是你需要***,所以这篇文章来讲讲,如果不会***,该如何安装Docker. ...
- python目标定位(借鉴csdn上大神)
写博客是为了记录下来,毕竟好多东西记不住,看过就忘了,收藏又太多,还不如搬运到自己博客下面,随时可翻~~~ 近期再学目标识别与定位,看着原理都很简单,但是真自己做,又觉得困难重重. csdn上一个大神 ...
- 高并发的socket的高性能设计【转】
转自:https://blog.csdn.net/quincyfang/article/details/44654351 高性能数据传输系统的框架设计 1 引言 随着互联网和物联网的高速发展,使用网络 ...