【HDU6286】2018(容斥)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=6286

题目:


Problem Description

Given a,b,c,d, find out the number of pairs of integers (x,y) where a≤x≤b,c≤y≤d and x⋅y is a multiple of 2018.

Input

The input consists of several test cases and is terminated by end-of-file.

Each test case contains four integers a,b,c,d.

Output

For each test case, print an integer which denotes the result.

## Constraint

* 1≤a≤b≤109,1≤c≤d≤109
* The number of tests cases does not exceed 104.

Sample Input

1 2 1 2018

1 2018 1 2018

1 1000000000 1 1000000000

Sample Output

3

6051

1485883320325200

 

解题思路:


2018只能分解成1*2018和2*1009。

所以要求的二元组应该是下面四种形式:

a:(1k,2018k)A:(2018k,1k)

b(2k,1009k)  B:(1009k,2k)

其中定义a1、a2表示可取值中有多少个是1的倍数(即k的数目),有多少个是2018的倍数,A1、A2同理。

为了少考虑a和b重复的二元组,b1、b2表示可取值中有多少个是2的倍数,有多少个是1009的奇数倍。B1、B2表示可取值中有多少个是1009的奇数倍(注意不要求错!!),有多少个是2的倍数。

(emmm好像定义的有些麻烦,其实b1定义成可取值中有多少个是2的倍数但不是2018的倍数可以简化式子,算了,就这么写吧,殊途同归)

最终得到式子:

 ans = a1 * a2 + A1 * A2 - A1 * a2 + b1 * b2 + B1 * B2 - b2 * A1 - a2 * B1;

 

ac代码:


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
ll a, b, c, d;
ll Count(ll a, ll b, ll x)
{
    if(x == 1009)
    {
        ll m, n = b/x;
        if(a%x == 0) m = a/x;
        else m = a/x+1;
        if(m > n) return 0;
        else
        {
            if(m%2 == 0) return (n-m+1)/2;
            else return (n-m+2)/2;
        }
    }
    else return b/x - (a-1)/x;
}
int main()
{
    //freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
    while(scanf("%lld %lld %lld %lld", &a, &b, &c, &d) == 4)
    {
        ll a1, a2, A1, A2, b1, b2, B1, B2;
        a1 = b - a + 1; a2 = Count(c, d, 2018);
        A1 = Count(a, b, 2018); A2 = d - c + 1;
        b1 = Count(a, b, 2); b2 = Count(c, d, 1009);//b2也可以直接用1009倍数的个数-2018倍数的个数,倔强的我还是坚持自己的写法
        B1 = Count(a, b, 1009); B2 = Count(c, d, 2);
        ll ans = a1 * a2 + A1 * A2 - A1 * a2 + b1 * b2 + B1 * B2 - b2 * A1 - a2 * B1;
        cout << ans << endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值