题目链接:
http://codeforces.com/contest/1055/problem/C
题目思路
其实就是能移动gcd(ta,tb)的长度,然后尽量使他们对齐就行了
然后不一定刚好对齐,所以在不多出一点和多出一点这两种情况中选最大就行了
证明过程:
题解:要想使两组连续幸运天数尽可能的多,那就要想办法两组幸运区间要尽量对齐,那么我们就以右边界尽量对齐为基准,
给出两个区间 [la,ra]和 [lb,rb] (设ra<rb),gcd=gcd(ta,tb),我们要让ra靠近rb,只需将ra加上 m*gcd (m=(rb-ra)/gcd),相应的la也是加上同样的。为什么可以这样直接加呢?按道理不是应该加上 ta*k的吗?不急,我先给个样例:
4 6 12 和 11 13 18 ,按上面的方法,gcd=6,m=1,那么第一个区间靠近第二个区间就差6了,第一个区间加完(13-6)/6*6=6后就变成 [10,12] ,那么此时连续天数是2天,咦?
怎么能加6呢?应该是加12*k的啊?我来解释一下,第一个区间加完后[10,12]与第二个区间[11,13]的状态一定会存在,状态如下图所示:
就是说会在之后的某个区间,这里其实就是 [64,66](12*5)(加的值) 和 [65,67] (18*3)这两个区间,而这里12*5-18*3=6的,刚好是我们把第一个区间[4,6]变成[10,12]的m*gcd=6的值,那么这说明上面的方法是正确的。其实也就是看看 12*x+18*y=6 有没有整数解,因为 gcd(12,18)|6,根据裴蜀定理,一定有整数解。所以以后我们只需加上m*gcd就行了,因为ta*x+tb*y=m*gcd,而gcd(ta,tb)|m*gcd,故一定有整数解。
这篇讲的不错,总结的思路大概就是:
其实就是能移动gcd(ta,tb)的长度,然后尽量使他们对齐就行了
然后不一定刚好对齐,所以在不多出一点和多出一点这两种情况中选最大就行了
求出两个区间的差值:ra-rb,然后用gcd(ta,tb)
即ta*x+tb*y=x,的这个x尽量等于这个差值ra-rb。
那么x=((ra-rb)/gcd)*gcd,由于语法的特性使得x尽量靠近ra-rb了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int gcd(int a,int b)
{
return b? gcd(b,a%b):a;
}
int solve(int a,int b,int l,int r)
{
return min(b,r)-max(a,l)+1;
}
int main()
{
int la,ra,ta,lb,rb,tb;
cin>>la>>ra>>ta;
cin>>lb>>rb>>tb;
if(ra>rb){
swap(ra,rb);
swap(la,lb);
swap(ta,tb);
}
int gc=gcd(ta,tb);
int m=(rb-ra)/gc;
int ans=0;
ans=max(ans,solve(la+m*gc,ra+m*gc,lb,rb));
ans=max(ans,solve(la+m*gc+gc,ra+m*gc+gc,lb,rb));
printf("%d\n",ans);
return 0;
}