ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4774 [NOI2018] 屠龙勇士 - 数论、中国剩余定理

2021-06-30 09:34:34  阅读:172  来源: 互联网

标签:P4774 return lc Read ll include ch 屠龙 NOI2018


题意

给出 \(n\) 个线性同余方程构成的方程组 \(\begin{cases} a_1x\equiv b_1 \pmod{p_1} \\ a_2x\equiv b_2 \pmod{p_2} \\ \dots \\ a_nx\equiv b_n \pmod{p_n} \end{cases}\)

问其大于等于某个数的最小解,如果无解输出 \(-1\)。

题解

首先考虑某个线性同余方程 \(a_ix\equiv b_i \pmod{p_i}\) 怎么解。它其实等价于不定方程 \(a_ix+p_iy=b_i\),设其特解为 \(\begin{cases} x=x_0 \\ y=y_0 \end{cases}\),那么其通解就是 \(\begin{cases} x=x_0+k\frac{p_i}{\gcd(p_i,a_i)} \\ y=y_0+k\frac{a_i}{\gcd(p_i,a_i)} \end{cases},k\in \mathbb{Z}\)。转化成同余式就是 \(x\equiv x_0 \pmod{\frac{p_i}{\gcd(p_i,a_i)}}\)。

然后套 exCRT 即可。注意 exCRT 过程中一定要多取模!!!

代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <set>
#include <cassert>
#include <algorithm>
using namespace std;
#define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti)
#define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti)
template<typename T> void Read(T &x){
	x=0;int _f=1;
	char ch=getchar();
	while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar();
	while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
	x=x*_f;
}
template<typename T,typename... Args> void Read(T &x,Args& ...others){
	Read(x);Read(others...);
}
typedef long long ll;
ll Mul(ll a,ll b,ll p){
	a=(a%p+p)%p,b=(b%p+p)%p;
	ll res=0;
	while(b){
		if(b&1) res=(res+a)%p;
		b>>=1,a=a*2%p;
	}return res;
}
ll Lcm(ll a,ll b){
	if(!a||!b) return a^b;
	return a/__gcd(a,b)*b;
}
ll ExEuclid(ll a,ll b,ll &x,ll &y){
	if(!b){x=1,y=0;return a;}
	ll t,g=ExEuclid(b,a%b,t,y);
	x=y,y=t-a/b*y;return g;
}
bool SolveEq(ll a,ll b,ll c,ll &x){//ax=b(mod c)
	ll y,g=ExEuclid(a,c,x,y);
	if(b%g) return 0;
	x=Mul(x,b/g,c/g);return 1;
}
const int N=1e5+5;
int T,n,m;ll a[N],p[N],rew[N],atk[N],sword[N];
int main(){
	Read(T);
	while(T--){
		Read(n,m);
		For(i,1,n) Read(a[i]);
		For(i,1,n) Read(p[i]);
		For(i,1,n) Read(rew[i]);
		For(i,1,m) Read(atk[i]);
		multiset<ll> sw(atk+1,atk+m+1);
		For(i,1,n){
			auto it=sw.upper_bound(a[i]);
			if(it!=sw.begin()) --it;
			sword[i]=*it;sw.erase(it);
			sw.insert(rew[i]);
		}
		ll lc=1,x=0,mx=0,succ=1;
		For(i,1,n){
			ll sol1;
			if(!SolveEq(sword[i],a[i],p[i],sol1)){
				puts("-1");succ=0;break;
			}
			ll cur=sol1;p[i]/=__gcd(p[i],sword[i]);
			if(!SolveEq(lc,((cur-x)%p[i]+p[i])%p[i],p[i],sol1)){
				puts("-1");succ=0;break;
			}
//			assert(lc*sol1+x==p[i]*sol2+cur);
			ll mod=Lcm(lc,p[i]);
			x=(Mul(lc,sol1,mod)+x+mod)%mod;lc=mod;
			mx=max(mx,(a[i]+sword[i]-1)/sword[i]);
		}
		if(succ){
			ll k=(mx-x+lc-1)/lc;
			printf("%lld\n",x+k*lc);
		}
	}
	return 0;
}

标签:P4774,return,lc,Read,ll,include,ch,屠龙,NOI2018
来源: https://www.cnblogs.com/alan-zhao-2007/p/p4774-sol.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有