【容斥定理】sdut-4219 Four-tuples

Step1 Problem:

给你 l1, r1, l2, r2, l3, r3, l4, r4, 让你找满足 li <= xi <= ri 同时 x1 != x2, x2 != x3, x3 != x4, x4 != x1的 元组 (x1, x2, x3, x4) 的个数 结果 MOD 1e9+7.
数据范围:
1 <= li <= ri <= 1e9.

Step2 Ideas:

我们可以满足 li <= xi <= ri 同时 (x1==x2 或 x2 == x3 或 x3 == x4 或 x4 == x1) 的元组 (x1, x2, x3, x4) 的个数,然后拿满足条件 li <= xi <= ri 的个数 - 它就是结果。

满足条件 li <= xi <= ri 很好求,核心是求满足 li <= xi <= ri 同时 (x1==x2 或 x2 == x3 或 x3 == x4 或 x4 == x1) 的元组 (x1, x2, x3, x4) 的个数。
也就是容斥定理:
在条件 li <= xi <= ri 的前提下:
我们设 x1 == x2 为序号 1
我们设 x2 == x3 为序号 2
我们设 x3 == x4 为序号 3
我们设 x4 == x1 为序号 4
加去满足序号 1, 2, 3, 4 的个数
减上满足序号 1&&2, 1&&3, 1&&4, 2&&3, 2&&4, 3&&4 的个数
加上满足序号 1&&2&&3, 1&&2&&4, 1&&3&&4, 2&&3&&4 的个数
减去满足序号 1&&2&&3&&4 的个数
然后拿满足条件 li <= xi <= ri 的个数 减去 它即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int MOD = 1e9+7;
struct node
{
    ll l, r, len;
};
node a[5];
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        ll ans = 1;
        for(int i = 1; i <= 4; i++)
        {
            scanf("%lld %lld", &a[i].l, &a[i].r);
            a[i].len = a[i].r - a[i].l + 1;
            ans = ans * a[i].len;//满足条件 li <= xi <= ri 的个数
            ans %= MOD;
        }
        ll r12, r13, r14, r23, r24, r34;//预处理区间公共长度
        ll r123, r124, r134, r234;
        ll r1234;
        r12 = min(a[2].r, a[1].r) - max(a[2].l, a[1].l) + 1;
        if(r12 < 0) r12 = 0;
        r13 = min(a[3].r, a[1].r) - max(a[3].l, a[1].l) + 1;
        if(r13 < 0) r13 = 0;
        r14 = min(a[4].r, a[1].r) - max(a[4].l, a[1].l) + 1;
        if(r14 < 0) r14 = 0;
        r23 = min(a[3].r, a[2].r) - max(a[3].l, a[2].l) + 1;
        if(r23 < 0) r23 = 0;
        r24 = min(a[4].r, a[2].r) - max(a[4].l, a[2].l) + 1;
        if(r24 < 0) r24 = 0;
        r34 = min(a[4].r, a[3].r) - max(a[4].l, a[3].l) + 1;
        if(r34 < 0) r34 = 0;

        r123 = min(min(a[1].r, a[2].r), a[3].r) - max(max(a[1].l, a[2].l), a[3].l) + 1;
        if(r123 < 0) r123 = 0;
        r124 = min(min(a[1].r, a[2].r), a[4].r) - max(max(a[1].l, a[2].l), a[4].l) + 1;
        if(r124 < 0) r124 = 0;
        r134 = min(min(a[1].r, a[4].r), a[3].r) - max(max(a[1].l, a[4].l), a[3].l) + 1;
        if(r134 < 0) r134 = 0;
        r234 = min(min(a[4].r, a[2].r), a[3].r) - max(max(a[4].l, a[2].l), a[3].l) + 1;
        if(r234 < 0) r234 = 0;

        r1234 = min(min(min(a[1].r, a[2].r), a[3].r), a[4].r) - max(max(max(a[1].l, a[2].l), a[3].l), a[4].l) + 1;
        if(r1234 < 0) r1234 = 0;

//        printf("%lld %lld %lld %lld %lld %lld\n", r12, r13, r14, r23, r24, r34);
//        printf("%lld %lld %lld %lld\n", r123, r124, r134, r234);
//        printf("%lld\n", r1234);
//        printf("%lld\n", ans);

        ll tmp = 0;//加
        tmp += ((r12 * a[3].len)%MOD * a[4].len)%MOD;
        tmp %= MOD;

        tmp += ((r23 * a[1].len)%MOD * a[4].len)%MOD;
        tmp %= MOD;

        tmp += ((r34 * a[1].len)%MOD * a[2].len)%MOD;
        tmp %= MOD;

        tmp += ((r14 * a[2].len)%MOD * a[3].len)%MOD;
        tmp %= MOD;

        //printf("%lld\n", tmp);
        ans = (ans - tmp)%MOD + MOD;
        ans %= MOD;

     //   printf("%lld\n", ans);

        tmp = 0;//减
        tmp += (r123 * a[4].len)%MOD;
        tmp %= MOD;

        tmp += (r12 * r34)%MOD;
        tmp %= MOD;

        tmp += (r124 * a[3].len)%MOD;
        tmp %= MOD;

        tmp += (r234 * a[1].len)%MOD;
        tmp %= MOD;

        tmp += (r23 * r14)%MOD;
        tmp %= MOD;

        tmp += (r134 * a[2].len)%MOD;
        tmp %= MOD;



     //   printf("%lld\n", tmp);
        ans = ans + tmp;
        ans %= MOD;

        tmp = 0;//加四个减一个所以相当于加三个
        tmp += (r1234)%MOD;
        tmp %=MOD;

        tmp += (r1234)%MOD;
        tmp %=MOD;

        tmp += (r1234)%MOD;
        tmp %=MOD;


     //   printf("%lld\n", tmp);
        ans = (ans - tmp)%MOD + MOD;
        ans %= MOD;

        printf("%lld\n", ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/bbbbswbq/article/details/81053977