hdu - 4790 - Just Random(容斥 + 组合数学)

题意:在 [a, b] 取一个整数 x,在 [c, d] 取一个整数 y,求满足 (x + y) % p = m 的 (x, y) 的对数(0 <= a <= b <= 10 ^ 9, 0 <=c <= d <= 10 ^ 9, 0 <= m < p <= 10 ^ 9)。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4790

——>>2013年成都区赛最后一题,当时TLE6次无果。。敲打。。加上 B 的无限WA,铁铁地铁了。。

。。。。。。。

设 F(a, b) 表示 [0, a] 取 x,[0, b] 取 y 的满足条件的 (x, y) 对数,则:

结果 = F(b, d) - F(a - 1, d) - F(c - 1, b) + F(a - 1, c - 1)

怎么求 F 呢?

因为 (x + y) % p,所以,可以 (x % p + y % p) % p

[0, a] 各点依次 % p 后的序列是:0, 1, 2, ..., p - 1,  0, 1, 2, ..., p - 1,0, 1, 2, ...(共 (a + 1) / p 个完整周期)

[0, b] 各点依次 % p 后的序列是:0, 1, 2, ..., p - 1,  0, 1, 2, ..., p - 10, 1, 2, ...(共 (b + 1) / p 个完整周期)

[0, a] 上的一个完整周期,和 [0, b] 上的一个完整周期组合,可以得到 p 个 (x, y) 满足条件(前者取一个数x, 后者一定可以找到一个相应的 y,使得(x + y) % p = m,这时将x, y同比例一个增大一个减小,得到的 (x + k, y - k) 也满足条件。。共有 p 个)。。

所以,[0, a] 的完整区间与 [0, b] 的完整区间组合,可得到 ((a + 1) / p) *((b + 1) / p)* p 个 (x, y) 满足条件(蓝色这层括号不可少!!敲打。。

设 ar = (a + 1) % p

设 br = (b + 1) % p

[0, a] 最后剩下的不完整片段为 0, 1, 2, ..., ar - 1

[0, b] 最后剩下的不完整片段为 0, 1, 2, ..., br - 1

[0, a] 的剩余区间 [0, ar - 1],与 [0, b] 的一个完整区间 [0, p - 1] 组合,可得到 ar 个满足要求的 (x, y) 。。

[0, b] 的剩余区间 [0, br - 1],与 [0, a] 的一个完整区间 [0, p - 1] 组合,可得到 br 个满足要求的 (x, y) 。。

[0, a] 的剩余区间 [0, ar - 1],与 [0, b] 的所有完整区间 [0, p - 1] 组合,可得到 ar *((b + 1) / p)个满足要求的 (x, y) 。。

[0, b] 的剩余区间 [0, br - 1],与 [0, a] 的所有完整区间 [0, p - 1] 组合,可得到 br * ((a + 1) / p)个满足要求的 (x, y) 。。

最后,考虑 [0, a] 的剩余区间与[0, b]的剩余区间组合。。

先来一次--ar, --br,方便后面处理。。

如果在 [0, br] 上取0,[0, ar] 上就必须取 m,但是 m 能不能取到呢?不一定,要对 m 进行分类讨论。。

当 ar > m 时,对于区间 [0, ar](别用 >= 放到这里来哦:原因请测试 0 0 0 0 10 0 这组样例)

这样移动:0 <-- m,[0, br] 上这样移动:0 --> xx,此时可得到 min(m + 1, br + 1)个满足要求的 (x, y)。。

这样移动:<-- ar,要使 (ar + y ) % p = m,则最小的 miny = (m - ar + p) % p,如果 miny <= br,则可得到 br - miny + 1 个满足要求的 (x, y)。。(这个地方要想通哦,为什么ar往左的时候不用固定边界?当 y 到达右边界 br,而 x 未到 m 时,说明 (m, x) 之间的数需要 y 取小于0 的数或者大于 br 的数才可以,这是不可能的;当 x 越过了 m 时,说明 [x, m] 之间的数既可以取两个不同的位置,并不是重复)

当 ar < m 时,对于区间 [0, ar]:

即使 [0, br] 上取 y = 0 时不可行的。。

要使 (ar + y ) % p = m,则最小的 miny = (m - ar + p) % p,如果 miny <= br,则可得到 min(ar + 1, br - miny + 1) 个满足要求的 (x, y)。。

当 ar == m 时,可得 min(ar + 1, br + 1) 个满足要求的(x, y)。。

于是可求得 F ,继续求得最终的结果。。

#include <cstdio>
#include <algorithm>

using std::min;

typedef long long ll;

ll F(ll a, ll b, ll p, ll m)
{
    if (a < 0 || b < 0) return 0;

    ll ret = 0;

    ret =  ((a + 1) / p) * ((b + 1) / p) * p;
    ll ar = (a + 1) % p;
    ll br = (b + 1) % p;
    if (!ar && !br) return ret;

    if (ar)
    {
        ret += ar * ((b + 1) / p);
    }
    if (br)
    {
        ret += br * ((a + 1) / p);
    }
    if (!ar || !br) return ret;

    --ar;
    --br;
    ll miny = (m - ar + p) % p;
    if (ar > m)
    {
        ret += min(m + 1, br + 1);
        if (miny <= br)
        {
            ret += br - miny + 1;
        }
    }
    else if (ar < m)
    {
        if (miny <= br)
        {
            ret += min(ar + 1, br - miny + 1);
        }
    }
    else
    {
        ret += min(ar + 1, br + 1);
    }

    return ret;
}

ll Gcd(ll a, ll b)
{
    return b == 0 ? a : Gcd(b, a % b);
}

int main()
{
    int T, kase = 0;
    ll a, b, c, d, p, m;

    scanf("%d", &T);
    while (T--)
    {
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &a, &b, &c, &d, &p, &m);
        ll A = F(b, d, p, m) - F(a - 1, d, p, m) - F(c - 1, b, p, m) + F(a - 1, c - 1, p, m);
        ll B = (b - a + 1) * (d - c + 1);
        ll gcd = Gcd(A, B);
        printf("Case #%d: %I64d/%I64d\n", ++kase, A / gcd, B / gcd);
    }

    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值