题目传送门
题意很明确:
给定区间,求区间内2个数乘积是某个质数的倍数的组合有多少个
思路:
简单的回顾一下,先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。所以这个题就是用这个。
第一种方法: e * (d-c+1) + f * (b-a+1) - e*f,就是下面的代码。
第二种方法:我们逆向思考,我们需要的是符合条件的,那么是不是总数 - 不符合条件数即可呢?我们不妨设len1为第一个区间的长度,len2为第二个区间的长度,则题目中的总数即为len1 * len2 , 不符合条件的即为 (len1 - e) * (len2 - f) ,那么结果 res = len1 * len2 - (len1 - e) * (len2 - f)
代码:
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long a,b,c,d,e,f,g,h;
while(~scanf("%lld %lld %lld %lld",&a,&b,&c,&d))
{
long long e = b/2017 - (a-1)/2017; //第一个区间2017的倍数的个数
long long f = d/2017 - (c-1)/2017; //第二个区间2017的倍数的个数
long long res = e * (d-c+1) + f * (b-a+1) - e*f;
/*
e * (d-c+1) //第一个区间2017的倍数的个数 * 第二个区间数的个数 得出一个符合条件的集合
f * (b-a+1) //第二个区间2017的倍数的个数 * 第一个区间数的个数 得出一个符合条件的集合
e*f //第一个区间2017的倍数的个数 * 第二个区间2017的倍数的个数 得出上两个集合重复的部分
e * (d-c+1) + f * (b-a+1) - e*f //就是我们需要的答案,即有几种组合是2017的倍数
*/
//如果这样做的话,要注意a,c是不是2017的倍数
// e = b/2017 - a/2017;
// if(a%2017 == 0){
// e++;
// }
// f = d/2017 - c/2017;
// if(c%2017 == 0){
// f++;
// }
printf("%lld\n",res);
}
return 0;
}