给定两个区间,这两个区间内分别取x,y,求x * y是2018倍数的方案数。
2018的因数只有1、2、1009、、2018四个,所以想到左右区间找这几个因数的倍数,然后左右相乘再处理,组合的思想,分类讨论两个区间。需要求出某区间内某个数的倍数的个数,边界值的处理需要注意。。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 1e9 + 10;
ll cal(int a, int b, int base) //返回[a,b]区间内base的倍数的个数
{
ll l = (a - 1) / base;
ll r = b / base;
return r - l;
}
/*初始版本,写法有点啰嗦
void cal(int a, int b, ll& n2018, ll& n1009, ll& even)
{
ll left = (a - 1) / 2018;
ll right = b / 2018;
ll ans = right - left;
n2018 = ans;
//cout << n2018 << endl;
left = (a - 1) / 1009;
right = b / 1009;
ans = right - left;
n1009 = ans;
//cout << n1009 << endl;
left = (a - 1) / 2;
right = b / 2;
ans = right - left;
even = ans;
//cout << even << endl;
}
*/
int main()
{
ll a, b, c, d;
while(scanf("%lld", &a) != EOF)
{
scanf("%lld%lld%lld", &b, &c, &d);
ll l2018, l1009, leven;
ll r2018, r1009, reven;
l2018 = cal(a, b, 2018);
l1009 = cal(a, b, 1009);
leven = cal(a, b, 2);
r2018 = cal(c, d, 2018);
r1009 = cal(c, d, 1009);
reven = cal(c, d, 2);
//cal(a, b, l2018, l1009, leven);
//cal(c, d, r2018, r1009, reven);
ll ans = l2018 * (d - c + 1) + (l1009 - l2018) * reven + (leven - l2018) * r1009 + (b - a + 1 - leven - l1009 + l2018) * r2018;
printf("%lld\n", ans);
}
return 0;
}