题目链接

loj#2721. 「NOI2018」屠龙勇士

题解

首先可以列出线性方程组

方程组转化为在模p意义下的同余方程

因为不保证pp 互素,考虑扩展中国剩余定理合并

方程组是带系数的,我们要做的是在%p意义下把系数除过去,(系数为atk[i])

(atk[i],p[i]) 不等于1时无逆元,此时仍可能有解

很显然无解的情况就是

瞎jb猜的,无解的话就是%p[i]意义下atk[i] != 0 ,a[i] = 0

考虑原方程式ai = atk{i] * x + p[i] * y

方程两边同除gcd(pi,atki)解不变 此时atki,pi此时保证了atki与pi互素

若ai不能被整除也是无解的

反正也没有-1的情况....

扩展crt

着实被winXP下输出lld坑了一把....顺带被自己抄的splay坑了一把

/*
苟活者在淡红的血色中,会依稀看到微茫的希望
*/ #include<bits/stdc++.h>
using namespace std;
inline long long read() {
long long x;
scanf("%lld",&x);
return x;
}
int n,m;
#define LL long long
const int maxn = 500007;
LL a[maxn],p[maxn]; // x atk[i] = a[i] ( % p[i])
LL atk[maxn],tatk[maxn]; struct Splay {
#define fa(x) T[x].fa
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
#define root T[0].ch[1]
struct node
{
LL val,rev,siz,fa,ch[2];
}T[maxn];
LL tot;
void clear() {
tot = 0; root = 0;
for(LL i = 1; i <= maxn; i++) T[i].val = T[i].rev = T[i].siz = T[i].fa = T[i].ch[0] = T[i].ch[1] = 0;
}
LL ident(LL x){return T[fa(x)].ch[0]==x?0:1;}
void connect(LL x,LL fa,LL how){T[fa].ch[how]=x;T[x].fa=fa;}
void update(LL x){T[x].siz=T[ls(x)].siz+T[rs(x)].siz+T[x].rev;}
void rotate(LL x)
{
LL Y=T[x].fa,R=T[Y].fa;
LL Yson=ident(x),Rson=ident(Y);
LL B=T[x].ch[Yson^1];
connect(B,Y,Yson);
connect(Y,x,Yson^1);
connect(x,R,Rson);
update(Y);update(x);
}
void splay(LL x,LL to)
{
to=T[to].fa;
while(T[x].fa!=to)
{
if(T[fa(x)].fa==to) rotate(x);
else if(ident(x)==ident(fa(x))) rotate(fa(x)),rotate(x);
else rotate(x),rotate(x);
}
}
LL newnode(LL fa,LL val) {
T[++tot].fa=fa;
T[tot].val=val;
T[tot].rev=T[tot].siz=1;
return tot;
}
LL find(LL val)
{
LL now=root;
while(1)
{
if(T[now].val==val) {splay(now,root);return now;}
LL nxt=T[now].val<val;
now=T[now].ch[nxt];
}
}
void insert(LL val)
{
if(root==0) {root=newnode(0,val);return ;}
LL now=root;
while(1)
{
T[now].siz++;
if(T[now].val==val) {T[now].rev++;splay(now,root);return ;}
LL nxt=val<T[now].val?0:1;
if(!T[now].ch[nxt]) {T[now].ch[nxt]=newnode(now,val);splay(now,root);return ;}
now=T[now].ch[nxt];
}
}
void erase(LL val)
{
LL now=find(val);
if(T[now].rev>1) {T[now].rev--;T[now].siz--;return ;}
else if(!ls(now)&&!rs(now)) {root=0;return ;}
else if(!ls(now)) {root=rs(now);T[rs(now)].fa=0;return ;}
LL left=ls(now);
while(rs(left)) left=rs(left);
splay(left,ls(now));
connect(rs(now),left,1);
connect(left,0,1);
//update(rs(now));
update(left);//
}
LL pre(LL val)
{
LL now=root,ans=-1e13;
while(now)
{
if(T[now].val<=val) ans=max(ans,T[now].val);
LL nxt=val<=T[now].val?0:1;
now=T[now].ch[nxt];
}
return ans == -1e13 ? -1 : ans;
}
LL nxt(LL val)
{
LL now=root,ans=1e13;
while(now)
{
if(T[now].val>val) ans=min(ans,T[now].val);
LL nxt=val<T[now].val?0:1;
now=T[now].ch[nxt];
}
return ans;
}
}Sp;
LL gcd(LL a,LL b) {return b == 0 ? a : gcd(b,a % b);}
LL exgcd(LL a,LL b,LL &x,LL &y) {
if(b == 0) {x = 1,y = 0;return a; }
LL ret = exgcd(b,a % b,x,y);
LL tmp = x;x = y;y = tmp - (a / b) * y;
return ret;
}
LL inv(LL a,LL b) {
LL x,y;
exgcd(a,b,x,y);
while(x < 0) x += b;
return x;
}
void work() {
LL ans = 0;
for(int i = 1;i <= n;++ i) {
ans = std::max(ans,a[i] % atk[i] == 0 ? a[i] / atk[i] : a[i] / atk[i] + 1);
}
printf("%lld\n",ans);
}
LL M[maxn],C[maxn];
inline LL add(LL x,LL y,LL mod) { return x + y >= mod ? x + y - mod : x + y; }
LL mul(LL x,LL k,LL mod) {
LL ret = 0 ;
x %= mod;
for(;k;k >>= 1,x = add(x,x,mod))
if(k & 1) ret = add(ret,x,mod);
return ret;
}
bool flag = false;
void init() {
Sp.clear();
n = read(),m = read();
flag = false;
//puts("haha");
for(int i = 1;i <= n;++ i) a[i] = read();
for(int i = 1;i <= n;++ i){ p[i] = read();if(p[i] != 1) flag = true; }
for(int j = 1;j <= n;++ j) tatk[j] = read();
//printf("%d %d %d\n",n,m,flag);
for(int k,i = 1;i <= m;++ i)
k = read(),Sp.insert(k);
for(int i = 1;i <= n;++ i) {
//puts("asdasd");
LL p = Sp.pre(a[i]);
if(p == -1) p = Sp.nxt(a[i]);
atk[i] = p;
Sp.erase(p);
Sp.insert(tatk[i]);
}
if(!flag) {work();/*puts("haha");*/return; }
int num = 0;
for(int i = 1;i <= n;++ i) {
a[i] %= p[i],atk[i] %= p[i];
if(!a[i] && !atk[i]) continue;
else if(!atk[i]){puts("-1");return;}
LL d = gcd(atk[i],p[i]);
if(a[i] % d != 0) {continue; }
a[i] /= d,atk[i] /= d,p[i] /= d;
C[++ num] = mul(a[i] , ((inv(atk[i],p[i]) % p[i] + p[i]) % p[i]),p[i]);
M[num] = p[i];
}
LL m = M[1],A = C[1],x,y,t;
for(int i = 2;i <= num;++ i) {
LL d = exgcd(m,M[i],x,y);
t = (M[i] / d);
//if((C[i]-A)%d == 0 || (a[i] - A) % d == -0 ) {
x = mul((x % t + t) % t,(((C[i] - A) / d) % t + t) % t,t);
LL MOD = (m / d) * (M[i]);
A = (mul(m , x, MOD) + A % MOD) % MOD;
m = MOD;
// else {puts("-1"); return;};
}
A = (A % m + m) % m;
printf("%lld\n",A);
} int main() {
freopen("dragon.in","r",stdin); freopen("dragon.out","w",stdout);
int t = read();
while(t --) {
init();
}
return 0;
}

最新文章

  1. 快速Android开发系列网络篇之Retrofit
  2. 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架
  3. HDU 1839
  4. member template
  5. 获取edit焦点,打开和关闭软键盘
  6. fixed的left:50%,漂浮
  7. 数字信号处理实验(四)&mdash;&mdash;数字滤波器结构
  8. Winform基础
  9. HDU 5056 Boring Count --统计
  10. 微信公开课PRO版张小龙演讲全文
  11. Icon资源详解[1]
  12. jQuery中的选择器&lt;思维导图&gt;
  13. Linux 寻找安装路径
  14. C#利用 string.Join 泛型集合快速转换拼接字符串
  15. 探索未知种族之osg类生物---渲染遍历之Renderer::draw()简介
  16. Linux 命令详解(九)轻易删除OpenSSL 的后果
  17. 【C/C++】一道试题,深入理解数组和指针
  18. TortoiseSVN忽略文件夹
  19. 【sql server】&quot;已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行&quot; 解决方案
  20. http请求和返回的head字段

热门文章

  1. linux源码安装nginx
  2. “榕树下&#183;那年”移动app ( hybrid ) 开发总结
  3. 解决windows文件夹不能自动刷新的问题
  4. 2016.5.24——Intersection of Two Linked Lists
  5. 配置虚拟机时间使其与国内时间同步,linux时间 ntp
  6. 5 - django-csrf-session&amp;cookie
  7. ajax.BeginForm异步提交表单并显示更新数据
  8. asp.net mvc 本地化 默认的错误提示
  9. C++ : Boost : Rational 有理数类
  10. [USACO16OPEN]262144