Mail.Ru Cup 2018 Round 2 C. Lucky Days (数论,裴蜀定理)
Mail.Ru Cup 2018 Round 2 C. Lucky Days
-
题意:给你两个区间\([l_a,r_a]\)和\([l_b,r_b]\),可以分别移动\(k_1*t_a\)和\(k_2*t_b\)的距离,问你两个区间相交的最大部分是多少
-
题解:我们从\(k_1*t_a+k_2*t_b=x\)入手,根据裴蜀定理,\(gcd(t_a,t_b)|x\),也就是说,我们移动区间\(a\)和\(b\)时,二者的相对距离会变化\(gcd(t_a,t_b)\)的倍数,先算出两个区间相隔的距离\(dis\),那么应该移动的距离为\(dis/gcd(t_a,t_b)*gcd(t_a,t_b)\)和\(dis/gcd(t_a,t_b)*gcd(t_a,t_b)+gcd(t_a,t_b)\),二者答案取最大即可
-
代码:
#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 la,ra,ta; ll lb,rb,tb; ll cal(ll la,ll ra,ll lb,ll rb){ return max(1ll*0,min(ra,rb)-max(la,lb)+1); } int main() { scanf("%lld %lld %lld",&la,&ra,&ta); scanf("%lld %lld %lld",&lb,&rb,&tb); ll d=gcd(ta,tb); if(ta==tb){ printf("%lld\n",cal(la,ra,lb,rb)); return 0; } if(la<=lb){ ll dis=(lb-la)/d*d; la+=dis,ra+=dis; printf("%lld\n",max(cal(la,ra,lb,rb),cal(la+d,ra+d,lb,rb))); } else{ ll dis=(la-lb)/d*d; lb+=dis,rb+=dis; printf("%lld\n",max(cal(la,ra,lb,rb),cal(la,ra,lb+d,rb+d))); } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮