ABC193 E-Oversleeping 题解

暴力做法:按题意模拟

正确做法: E X C R T EXCRT EXCRT

出题人怕人看不出是解同余方程组,专门把柿子糊脸上了(。

根据题意,要找到一个最小时间 t t t 满足这个方程组:

{      t ≡ i      ( m o d     ( 2 X + 2 Y )   )     ( i ∈ [ X , X + Y ) ) t ≡ j      ( m o d     ( P + Q )   )     ( j ∈ [ P , P + Q ) ) \left\{\begin{matrix} \ \ \ \ t\equiv i\ \ \ \ (mod\ \ \ (2X+2Y)\ )\ \ \ (i\in[X,X+Y))\\ t\equiv j\ \ \ \ (mod\ \ \ (P+Q)\ )\ \ \ (j\in[P,P+Q)) \end{matrix}\right. {    ti    (mod   (2X+2Y) )   (i[X,X+Y))tj    (mod   (P+Q) )   (j[P,P+Q))

虽然 X X X P P P 很大,但是 P P P Q Q Q 非常小,因此可以枚举 [ X , X + Y ) [X,X+Y) [X,X+Y) [ P , P + Q ) [P,P+Q) [P,P+Q) 的每一个 i , j i,j i,j来解这个方程组。 2 X + 2 Y 2X+2Y 2X+2Y P + Q P+Q P+Q 不一定互质,因此需要 E X C R T EXCRT EXCRT 合并求解。

没了。

Code
#include<bits/stdc++.h>
#define N 200006
#define LL __int128
#define int long long 
using namespace std;
 
int T,t;
int X,Y,P,Q;
int mod1,mod2;
int a1,a2,b1,b2;
 
inline int qr()
{
	char a=0;int w=1,x=0;
	while(a<'0'||a>'9'){if(a=='-')w=-1;a=getchar();}
	while(a<='9'&&a>='0'){x=(x<<3)+(x<<1)+(a^48);a=getchar();}
	return w*x;
}
 
LL exgcd(LL a,LL b,LL &x,LL &y)
{
	if(!b)
	{
		x=1,y=0;
		return a;
	}
	LL d=exgcd(b,a%b,y,x);
	y-=a/b*x;
	return d;
}
 
LL mul(LL a,LL b,LL mod)
{
	LL ans=0;
	for(;b;a=(a+a)%mod,b>>=1)
		if(b&1) ans=(ans+a)%mod;
	return ans;
}
 
LL excrt()
{
    LL x,y,M=b1,ans=a1;
    LL a=M,b=b2,c=(a2-ans%b+b)%b;
    LL gcd=exgcd(a,b,x,y);
    LL bg=b/gcd;
    if(c%gcd!=0) return -1; 
    x=mul(x,c/gcd,bg);
    ans+=x*M;M*=bg;
    ans=(ans%M+M)%M;
    return (ans%M+M)%M;
}
 
signed main()
{
	T=qr();
	while(T--)
	{
		X=qr();Y=qr();
		P=qr();Q=qr();
		b1=(X+Y)<<1ll;
		b2=P+Q;
		LL ans=2e18;
		int opl=0;
		for(register int i=0;i<Y;i++)
			for(register int j=P;j<P+Q;j++)
			{
				a1=i+X;a2=j;
				LL ans1=excrt();
				if(ans1==-1) continue;
				opl=1;
				ans=min(ans1,ans);
			}
		if(opl) printf("%lld\n",(long long)ans);
		else printf("infinity\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值