CF1055C Solution

题目链接

题解

易得,左端点或右端点对齐时重叠部分一定是最大的。

可以发现,一定可以通过(+kcdot gcd(t_a,t_b))将左区间尽量右移直至差值(le gcd(t_a,t_b))。证明:根据裴蜀定理——若(a,b)是整数,且(d|gcd(a,b)),一定存在整数(x,y),使(ax+by=d)成立。一定存在(x,y)使得(t_ax-t_by(或t_bx-t_ay)=kcdot gcd(t_a,t_b))

此外,还需分类讨论(a,b)的左右顺序,以及左区间是否超过右区间。

AC代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int Gcd(int a,int b) {return (!b)?a:Gcd(b,a%b);}
int val(int l1,int l2,int r1,int r2,int t)
{
	l1+=t; r1+=t;
	return min(r1,r2)-max(l1,l2)+1;
}//计算重叠部分长度
signed main()
{
	int la,lb,ra,rb,ta,tb;
	scanf("%lld%lld%lld%lld%lld%lld",&la,&ra,&ta,&lb,&rb,&tb);
    //因为可能会出现0影响计算,l,r全部+1
	la++; ra++;
	lb++; rb++;	
	int gcd=Gcd(ta,tb),add=abs(ra-rb)/gcd*gcd,ans=0;//add:题解中的k·gcd(ta,tb)
    //1:a在前且不超过右区间,2:a在前且超过右区间
	ans=max(ans,max(val(la,lb,ra,rb,add)/*1*/,val(la,lb,ra,rb,add+gcd)/*2*/));
    //1:b在前且不超过右区间,2:b在前且超过右区间
	ans=max(ans,max(val(lb,la,rb,ra,add)/*3*/,val(lb,la,rb,ra,add+gcd)/*4*/));
	printf("%lld",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/violetholmes/p/14332465.html