题面如上:
这道题思路很简单:a1是x的一个因数,x又是b1的一个因数,可以很轻易的得知,x的范围是在a1到b1之间,然后需要写一个最大公约数的函数,如下:
这里方法有很多,就不一一列举了,然后通过判断
measure( x,a0)==a1和 x/measure(x,b0)*b0==b1
(两个数的最小公倍数等于这两个相乘再除以两个数的最大公因数,我这里颠倒顺序是防止x*b0爆int,一点点小细节。。)
上述两个等式即可,但是有那么简单就好了,我们不出意料的TLE(运行超时)了,这也不难想到,如果a1是1,b1是2e9,一个一个枚举必然是超时的,这时候就要想办法优化了。
方法一:也是最容易想到的,x既然是a1的倍数,那么我们可以每次增加a1啊,
但是,出现问题了,如果a1是1,每次增加1,明显还是不行。这个方法不行,pass。
方法二:看来要找藏在体面下更深的奥秘了,这里我就直接说了,我们知道x是b1的约数,那么可 以枚举从a1到根号b1,然后每次判断要同时判断两个数 x和 b1/x,任意一个符合都要加 一,当然二者相等就不用了。
这样这道题就解决了。
补充:如果x从a1开始不对,就从1开始。。。(PS:虽然我也不知道为啥从a1可是会被卡)。
注意:我在代码里是利用了measure(a,b)==k 等价于 measure(a/k,b/k)==1。
最后贴一下代码:
#include<bits/stdc++.h>
using namespace std;
int n;
inline int read()
{
int X = 0; bool flag = 1; char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') flag = 0; ch = getchar(); }
while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar(); }
if (flag) return X;
return ~(X - 1);
}
int measure(int x, int y)
{
int z = y;
while (x % y != 0)
{
z = x % y;
x = y;
y = z;
}
return z;
}
int main()
{
//ios_base::sync_with_stdio(false);
//cin.tie(nullptr);
//cout.tie(nullptr);
n = read();
while (n--) {
int a0, a1, b0, b1;
a0 = read();
a1 = read();
b0 = read();
b1 = read();
int cut = 0;
int p = a0 / a1;
int q = b1 / b0;
for (int i = a1; i * i<= b1; i++) {
if (b1 % i == 0) {
if (i % a1 == 0 && measure(p, i / a1) == 1 && measure(b1 / i, q) == 1)
cut++;
int y = b1 / i;
if (i == y)
continue;
if (y % a1 == 0 && measure(p, y / a1) == 1 && measure(b1 / y, q) == 1)
cut++;
}
}
printf("%d\n", cut);
}
return 0;
}
上面用到了快读,只是为了提高速度,并不是关键,再贴一个简易版的代码:
#include<bits/stdc++.h>
using namespace std;
int n;
int measure(int x, int y)//求x和y的最大公约数,辗转相除法。
{
int z = y;
while (x % y != 0)
{
z = x % y;
x = y;
y = z;
}
return z;
}
int main()
{
scanf_s("%d", &n);//scnaf_S是在vs里面的使用的,否则会报错,在其他地方可以直接使用scanf。
while (n--) {
int a0, a1, b0, b1;
scanf_s("%d %d %d %d", &a0, &a1, &b0, &b1);
int cut = 0;
int p = a0 / a1;
int q = b1 / b0;
for (int i = 1; i * i<= b1; i++) {
if (b1 % i == 0) //这一步是确定i是b1约数
{
if (i % a1 == 0 && measure(p, i / a1) == 1 && measure(b1 / i, q) == 1)
cut++;
int y = b1 / i;
if (i == y)
continue;
if (y % a1 == 0 && measure(p, y / a1) == 1 && measure(b1 / y, q) == 1)
cut++;
}
}
printf("%d\n", cut);
}
return 0;
}
第一次写题解,如果对你有帮助可以点赞,收藏哦!