返回顶部

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;
    }
    
posted @ 2021-11-18 14:58  Rayotaku  阅读(21)  评论(0编辑  收藏  举报