CF1055C 幸运的天数

1 CF1055C 幸运的天数

2 题目描述

时间限制 \(1s\) | 空间限制 \(256M\)

\(Bob\)\(Alice\) 经常参加各种编程比赛。像许多有竞争力的程序员一样,他们有时运气好,有时运气不好。他们注意到,他们的幸运与不幸的区间是具有周期性的。对于 \(Alice\) 来说,区间 \([𝑙_𝑎,𝑟_𝑎]\) 是幸运的,区间 \([𝑟_𝑎+1,𝑙_𝑎+𝑡_𝑎−1]\) 是不幸的,区间 \([l_a+𝑡_𝑎,r_a+𝑡_𝑎]\) 又是幸运的。换句话说,\(\forall k \in N\),区间 \([l_a + k*t_a, 𝑟_𝑎+𝑘*𝑡_𝑎]\) 对于 \(Alice\) 来说是幸运的。
\(Bob\) 的幸运区间也是类似,不过用 \(𝑙_𝑏、𝑟_𝑏、𝑡_𝑏\) 表示。 因此,\(\forall k \in N\),区间 \([l_b + k*t_b,𝑟_b+𝑘*𝑡_b]\) 对于 \(Bob\) 来说是幸运的。

\(Alice\)\(Bob\) 想一起参加团队比赛,所以他们想找出他们两个同时幸运的最大区间。

3 题解

根据裴蜀定理,我们每次可以将 \(l_a\)\(l_b\) 之间的距离增大 \(k*gcd(t_a, t_b)\) 个单位距离(\(k \in Z\))。这是因为 \(t_a * x - t_b * y = k * gcd(t_a, t_b) (k \in Z)\),这里的 \(x\) 表示 \(Alice\) 的区间往右移动的次数,\(y\) 就表示 \(Bob\) 的区间往右移动的次数。因此,如果 \(|l_a - l_b|\)\(gcd(t_a, t_b)\) 的整倍数,那么在某个位置两个开心的天数的起点一定对齐,我们只需要计算 \(min(r_a - l_a + 1, r_b -l_b + 1)\) 即可。

如果不是整倍数,那么最优答案一定是这两种之一:\(Alice\) 的开心区间的起点小于 \(Bob\) 的开心区间的起点且二者的差小于 \(gcd(t_a, t_b)\)\(Bob\) 的开心区间的起点大于 \(Bob\) 的开心区间的起点且二者的差小于 \(gcd(t_a, t_b)\)

容易看出,第一种情况中 \(Alice\) 的开心区间的起点可以通过将 \(Alice\) 的开心区间在第二种情况下的起点向左移动 \(gcd(t_a, t_b)\) 来得到,而 \(Bob\) 的区间完全不用移动。我们接下来考虑如何满足第二种情况。我们可以先进行判断,如果 \(l_a < l_b\),则将这两个人的所有指标互换,保证 \(l_a\) 一定大于等于 \(l_b\)。然后,我们将 \(Alice\) 的区间向左整体移动 \(\lfloor \frac{l_a - l_b}{gcd(t_a, t_b)} \rfloor * gcd(t_a, t_b)\) 个单位,\(Bob\) 的区间保持不变,这时 \(Alice\)\(Bob\) 的区间关系便满足第二种情况。这时答案便是 \(min(r_a, r_b) - max(l_a, l_b) + 1\)。我们再将 \(Alice\) 的区间向左整体移动 \(gcd(t_a, t_b)\) 个单位,\(Bob\) 的区间继续保持不变,此时两区间的关系满足第一种情况,答案为 \(min(r_a, r_b) - max(l_a, l_b) + 1\)。最终我们输出的就是以上这两种情况的最大值,即

\[min(r_a - \lfloor \frac{l_a - l_b}{gcd(t_a, t_b)} \rfloor * gcd(t_a, t_b), r_b) - max(l_a - \lfloor \frac{l_a - l_b}{gcd(t_a, t_b)} \rfloor * gcd(t_a, t_b), l_b) + 1 \]

\[\\min(r_a - (\lfloor \frac{l_a - l_b}{gcd(t_a, t_b)} \rfloor + 1) * gcd(t_a, t_b), r_b) - max(l_a - (\lfloor \frac{l_a - l_b}{gcd(t_a, t_b)} \rfloor + 1) * gcd(t_a, t_b), l_b) + 1 \]

二者的最大值。

4 代码(空格警告):

#include <iostream>
using namespace std;
int la, ra, ta;
int lb, rb, tb;
int Gcd, dis, len1, len2, r, ans;
int gcd(int a, int b)
{
    if (b == 0) return a;
    return gcd(b, a%b);
}
int main()
{
    cin >> la >> ra >> ta;
    cin >> lb >> rb >> tb;
    len1 = ra - la + 1;
    len2 = rb - lb + 1;
    if(la < lb)
	{
		swap(la, lb);
		swap(ta, tb);
		swap(ra, rb);
	}
    Gcd = gcd(ta, tb);
    dis = la - lb;
    r = dis / Gcd;
    if (dis % Gcd == 0) cout << min(len1, len2);
    else
    {
        la -= (r * Gcd);
        ra -= (r * Gcd);
        ans = max(ans, min(ra, rb) - max(la, lb) + 1);
        la -= Gcd;
        ra -= Gcd;
        ans = max(ans, min(ra, rb) - max(la, lb) + 1);
        cout << ans;
    }
    return 0;
}

欢迎关注我的公众号:智子笔记

posted @ 2021-02-06 10:23  David24  阅读(55)  评论(0编辑  收藏  举报