Mail.Ru Cup 2018 Round 2 C. Lucky Days(拓展欧几里得)

传送门

题意:

  a君,b君存在幸运周期;

  a君在第[L1+k*T1,R1+k*T1]天为幸运天;

  b君在第[L2+k*T2,R2+k*T2]天为幸运天;

  求a君,b君最大的连续的幸运天数;

题解:

  a君所有幸运天数开始的时刻为 La = L1+X*T1

  b君所有幸运天数开始的时刻为 Lb = L2+Y*T2

  假设 a君每个周期幸运的天数为 lena , b君的为 lenb

  ①如果∃X,Y使得 La = Lb ,那么答案就是 min(lena,lenb);

  ②反之,根据贪心策略,找到最小的非负整数 d1 使得 La + d1 = Lb 或最小的非负整数 d2 使得 La = Lb+d2; 

  两者取最大值;

  如何判断①是否成立呢?

    根据拓展欧几里得,使得①成立当且仅当 GCD(T1,T2)  |  abs(Lb-La);

  如果不成立,如何找到最小的d1,d2呢?

  

  令 gcd = GCD(T1,T2);  

  最小的非负整数 d1 = (L2-L1)%gcd(如果 d1 < 0 , d1 += gcd);

  d2=gcd-d1

  分别求解即可;

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define INFll 0x3f3f3f3f3f3f3f3f
 4 #define GCD(a,b) __gcd(a,b)
 5 #define ll long long
 6 
 7 struct Date
 8 {
 9     ll l,r,t;
10     ll len(){return r-l+1;};
11 }a,b;
12 
13 ll F(ll L1,ll R1,ll L2,ll R2)
14 {
15     return max(min(R1,R2)-max(L1,L2)+1,1ll*0)///答案有可能小于0,所以需要对0取个max;
16 }
17 ll Solve()
18 {
19     ll gcd=GCD(a.t,b.t);
20     ll c=abs(a.l-b.l);
21     if(c%gcd == 0)///情况①
22         return min(a.len(),b.len());
23     ll d1=((b.l-a.l)%gcd+gcd)%gcd;///情况②
24     ll d2=gcd-d1;
25     /*****************La+d1=Lb******************La=Lb+d2*********/
26     ll ans=max(F(0,a.r-a.l,d1,d1+b.r-b.l),F(0,b.r-b.l,d2,d2+a.r-a.l));
27     return ans;
28 }
29 int main()
30 {
31 //    freopen("C:\\Users\\hyacinthLJP\\Desktop\\in&&out\\contest","r",stdin);
32     scanf("%lld%lld%lld",&a.l,&a.r,&a.t);
33     scanf("%lld%lld%lld",&b.l,&b.r,&b.t);
34     printf("%lld\n",Solve());
35 
36     return 0;
37 }
View Code

猜你喜欢

转载自www.cnblogs.com/violet-acmer/p/10878200.html
今日推荐