题目链接
题意:问在a~b范围内分子,c ~ d 范围内的分母,共有多少个在化简后的和小于等于999
题解:因为数据量为1e12 很大所以暴力是不可能,但是我们可以想到,正因为有很多情况的原因就是可以化简,很大的数化简后可能就满足了情况,而我们也应该想到在某一个范围内的某一个倍数的求法,a/j,就是求0~a范围内j的倍数,想到这两点后其实离解出来也就不远了,再处理细节后就ok了。
下面是AC代码:
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
#define int long long int
#define endl '\n'
typedef pair<int, int> PII;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const int N = 1e4 + 7;signed main() {
int a, b, c, d, ans = 0;cin >> a >> b >> c >> d;for (int i = 1; i <= 999; i++) {
for (int j = 1; j <= 999; j++) {
if (i + j <= 999 && __gcd(i, j) == 1) {
if (min(b/i, d/j) - max((a-1)/i, (c-1)/j) > 0) {
//①ans += (min(b/i, d/j) - max((a-1)/i, (c-1)/j));// ②}}}}cout << ans;return 0;
}/* * * ┏┓ ┏┓+ + * ┏┛┻━━━┛┻┓ + + * ┃ ┃ * ┃ ━ ┃ ++ + + + * ████━████+ * ◥██◤ ◥██◤ + * ┃ ┻ ┃ * ┃ ┃ + + * ┗━┓ ┏━┛ * ┃ ┃ + + + +Code is far away from * ┃ ┃ + bug with the animal protecting * ┃ ┗━━━┓ 神兽保佑,代码无bug * ┃ ┣┓ * ┃ ┏┛ * ┗┓┓┏━┳┓┏┛ + + + + * ┃┫┫ ┃┫┫ * ┗┻┛ ┗┻┛+ + + + */
想到上面的一些性质后就可暴力来做了,暴力1 ~ 999 之内的数,两个for循环,将分母和分子的各种情况都暴力一遍,如果分母分子之和小于999且两者最大公约数为1(除去类似于1 / 2 和 3 / 6 的情况),这里有两个特殊注意的点。
①:这里 (a - 1) / i 是向下取整的做法,因为所需要的值应该是包含a 这个点的数的,所以为了不在算上a 所以要向下取整,防止算倍数的时候把a(a能够整除的情况下)也算上,c的也同理。
②:这里是前面是min值 ,后面取max值。
前面取min:
上下是除以相同的数的,所以是分别是左端点作比较,右端点作比较。因为这里的答案是受到两个区间控制的,所以去前面的最小值是因为 如果取最大的话,因为这是两个区间的右端,取最大值的时候可能会导致其中较小的超越区间,假设第一个数组的倍数有 1 , 2 ,3 ,4 而第二个数组有 1 , 2 ,3; 这样如果较小数组乘以的4 的话会越界。
后面取max:
这里和右边界类似,如果取最小值,可能其中的一个较大数组中取不到该值,所以应该减去那个大的,以防在某一数组中根本取不到那个值。
我们这里可以简单的举个例子:
例如两个右端点分别为 12 20; i=4 ,j=3
12/4=3 倍数分别为1 ,2 ,3
20/3=6 倍数分别为1 ,2, 3,4, 5,6
那么我们要找的是4/3
只有6/8,9/12,12/16 只有三种情况
在例如两个左端点是10 14 i=2 j=4
(10-1 )/2=4 , 倍数为1,2,3,4
(14-1)/4=3 倍数为1,2,3
这里应该是减去的部分,如果我减去的是少的话1,2,3倍都不在范围内,但是我们发现四倍的话,8<10不在范围内,但是16>14,在范围内,这种也是不满足情况的,8/16同样的在少的范围内 ,但不在大的范围内,所以,按照我们推的,应该是减去大的。
我们这里还可以总结一句话:前面取最小值因为是我们拿需要的,后面取最大值我们是减去不需要的。