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;
} 
												
											loj#2721. 「NOI2018」屠龙勇士的更多相关文章
- LOJ #2721. 「NOI2018」屠龙勇士(set + exgcd)
		
题意 LOJ #2721. 「NOI2018」屠龙勇士 题解 首先假设每条龙都可以打死,每次拿到的剑攻击力为 \(ATK\) . 这个需要支持每次插入一个数,查找比一个 \(\le\) 数最大的数(或 ...
 - LOJ 2721 「NOI2018」屠龙勇士——扩展中国剩余定理
		
题目:https://loj.ac/problem/2721 1.注意别一输入 p[ i ] 就 a[ i ] %= p[ i ] ,因为在 multiset 里找的时候还需要真实值. 2.注意用 m ...
 - 「NOI2018」屠龙勇士
		
「NOI2018」屠龙勇士 题目描述 小\(D\)最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照编号\(1-n\)顺序杀掉\(n\) 条巨龙,每条巨龙拥有一个初始的生命 值ai .同时 ...
 - 「NOI2018」屠龙勇士(EXCRT)
		
「NOI2018」屠龙勇士(EXCRT) 终于把传说中 \(NOI2018D2\) 的签到题写掉了... 开始我还没读懂题目...而且这题细节巨麻烦...(可能对我而言) 首先我们要转换一下,每次的 ...
 - POJ1061 青蛙的约会 和 LOJ2721 「NOI2018」屠龙勇士
		
青蛙的约会 Language:Default 青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 133470 Accep ...
 - 「NOI2018」屠龙勇士 解题报告
		
「NOI2018」屠龙勇士 首先对于每个龙用哪个剑砍,我们可以用set随便模拟一下得到. 然后求出拿这个剑砍这条龙的答案 \[ atk_ix-p_iy=a_i \] 其中\(atk_i\)是砍第\(i ...
 - 「NOI2018」屠龙勇士(CRT)
		
/* 首先杀每条龙用到的刀是能够确定的, 然后我们便得到了许多形如 ai - x * atki | pi的方程 而且限制了x的最小值 那么exgcd解出来就好了 之后就是扩展crt合并了 因为全T调了 ...
 - loj#2718. 「NOI2018」归程
		
题目链接 loj#2718. 「NOI2018」归程 题解 按照高度做克鲁斯卡尔重构树 那么对于询问倍增找到当前点能到达的高度最小可行点,该点的子树就是能到达的联通快,维护子树中到1节点的最短距离 s ...
 - Loj #2719. 「NOI2018」冒泡排序
		
Loj #2719. 「NOI2018」冒泡排序 题目描述 最近,小 S 对冒泡排序产生了浓厚的兴趣.为了问题简单,小 S 只研究对 *\(1\) 到 \(n\) 的排列*的冒泡排序. 下面是对冒泡排 ...
 
随机推荐
- Python练习-基于socket的FTPServer
			
# 编辑者:闫龙 import socket,json,struct class MySocket: with open("FtpServiceConfig","r&qu ...
 - ASP.NET mvc下在Controller下action的跳转方式
			
在ASP.NET mvc下,action有多种挑战方式: return RedirectToAction("Index");//一个参数时在本Controller下 如果Redir ...
 - [Openwrt 扩展上篇]USB挂载&U盘启动&Samba共享
			
最近偷懒,没学习,反想起自己的路由刷了Openwrt,正好闲置了一个硬盘想拿来做个网络硬盘,于是开始了折腾....这里将不谈论如何刷Openwrt,如何ssh,如何添加PPOE,如何添加相对应服务的包 ...
 - Linux移植随笔:对tslib库的ts_test测试程序代码的一点分析【转】
			
转自:http://www.latelee.org/embedded-linux/porting-linux-tstest-code.html 本文是作者对tslib库的ts_test.c文件进行分析 ...
 - linux下定时器介绍2--timer_create等函数集的使用示例
			
程序1:采用新线程派驻的通知方式 程序2:通知方式为信号的处理方式 #include <stdio.h>#include <time.h>#include <stdlib ...
 - 『实践』Java Web开发之分页(ajax)
			
1.需要用到的jar包.js文件 JSONArray().fromObject()需要的jar包: (1)commons-beanutils-1.8.3.jar (2)commons-collecti ...
 - 【CF767C】Garland
			
传送门啦 分析: 这个题我是看着翻译做的,感觉不是很难,很普通的一个树形dp 题目大意: 在一棵树上分离出三个子树,使这三个子树的点权和相等. 明确题目意思这个题就简单多了吧. 我们会发现每一棵子树的 ...
 - elasticsearch5.5-head
			
修改 elasticsearch/config/elasticsearch.yml 添加 http.cors.enabled: true http.cors.allow-origin: "* ...
 - Flask form
			
用户登录 #!/usr/bin/env python # -*- coding:utf- -*- from flask import Flask, render_template, request, ...
 - Unix IPC之基于共享内存的计数器
			
目的 本文主要实现一个基于共享内存的计数器,通过父子进程对其访问. 本文程序需基于<<Unix网络编程-卷2>>的环境才能运行.程序中大写开头的函数为其小写同名函数的包裹函数, ...