返回顶部

Caddi Programming Contest 2021(AtCoder Beginner Contest 193) E - Oversleeping (excrt,扩展中国剩余定理)

  • 题意:有一辆火车在\(A\)点和\(B\)点之间来回跑,到达\(B\)点后会停留一段时间,火车从\(A\)点出发,你刚开始就坐在火车上,你每过一段时间就会睡觉,问你能否在醒着的时候在\(B\)点下车.
  • 题解:题目中的不等关系式已经给的很明确了,因为区间范围最大为\(500\),所以我们可以\(O(n^2)\)枚举两个关系式的时间\(t_1\)\(t_2\),任意时间都满足:\((2X+2Y)*n+t_1\)\((P+Q)*n+t_2\),所以我们可以得到方程组:\(t \equiv t_1 \ mod (2X+2Y)\)\(t \equiv t_2 \ mod (P+Q)\),然后解一个\(excrt\)就行了.
  • 代码:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

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 k,ll mod){
	ll res=0;
	while(k){
		if(k&1) res=(res+a)%mod;
		k>>=1;
		a=(a+a)%mod;
	}
	return res;
}

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int _;
	cin>>_;
	while(_--){
		ll x,y,p,q;
		cin>>x>>y>>p>>q;

		ll ans=INT64_MAX;
		ll LCM=lcm(2*x+2*y,p+q);

		for(ll i=x;i<x+y;++i){
			for(ll j=p;j<p+q;++j){
				ll x1,y1;
				ll d=exgcd(2*x+2*y,-p-q,x1,y1);
				if((j-i)%d) continue;
				x1=x1*(j-i)/d;
				x1=(x1%LCM+LCM)%LCM;
				ans=min(ans,(mul(2*x+2*y,x1,LCM)+i)%LCM);
			}
		}

		if(ans==INT64_MAX) cout<<"infinity\n";
		else cout<<ans<<'\n';
	}

    return 0;
}

posted @ 2021-03-05 13:18  _Kolibri  阅读(138)  评论(0)    收藏  举报