题目传送门以及题意
洛谷体面:Hankson 的趣味题
yzoj 体面:小学生的数学题
题目:
已知 x 与 a 的最大公约数是 b,x 与 c 的最小公倍数数 d,请编程求出满足条件的 x 的数目。
解题思路
怎么其他题解都要转化什么 GCD式子,我来发篇简单的。
首先,由于,所以我们要枚举,学过数论的都知道一个特性:一个数超过的质因子至多有一个。
所以我们要质数筛出100000内的质数
所以总步骤是:
- 筛出质数
- 分解质因数
- 计算每个区间,求和
AC通过!
My Code:
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100000
typedef long long ll;
vector<int> prime;
bool isprime[MAXN + 10];
int n;
ll Answer;
ll Na0, Nb0, Na1, Nb1;
ll la, lb, ra, rb, l, r;
void PrimeSieve() { /*先不管是O(n)还是O(nlognlogn),筛就对了*/
memset(isprime, true, sizeof(isprime));
isprime[0] = isprime[1] = false;
for (int i = 2; i <= MAXN; i++) {
if (isprime[i]) {
prime.push_back(i);
for (int j = 2; i * j <= MAXN; j++) {
isprime[i * j] = false;
}
}
}
return;
}
void Count(ll *N, ll &To, int P) {
while (*N % P == 0) {
To++;
*N /= P;
}
return;
}
ll Sec(int l, int r) {
return (long long)r - (long long)l + 1ll;
}
int main() {
PrimeSieve();
ll a0, a1, b0, b1;
cin >> n;
while (n--) {
Answer = 1;
cin >> a0 >> a1 >> b0 >> b1;
bool isok = true;
if (a1 > a0 || b1 < b0) {
cout << 0 << "\n";
continue;
}
for (int i = 0; i < (int)prime.size(); i++) {
if (a0 == 1 && a1 == 1 && b0 == 1 && b1 == 1) {
break;
}
Na0 = 0;
Na1 = 0;
Nb0 = 0;
Nb1 = 0;
la = lb = l = 0;
ra = rb = r = MAXN;
Count(&a0, Na0, prime[i]);
Count(&a1, Na1, prime[i]);
Count(&b0, Nb0, prime[i]);
Count(&b1, Nb1, prime[i]);
if (Na1 > Na0 && Nb1 < Nb0) {
isok = false;
break;
}
la = Na1;
rb = Nb1;
if (Na0 > Na1) {
ra = Na1;
}
if (Nb0 < Nb1) {
lb = Nb1;
}
l = max(la, lb);
r = min(ra, rb);
if (r < l) {
isok = false;
break;
}
Answer *= Sec(l, r);
}
if (!(a0 == 1 && a1 == 1 && b0 == 1 && b1 == 1)) {
la = lb = l = 0;
ra = rb = r = MAXN;
if (a1 > a0 || b1 < b0) {
isok = false;
}
if (a1 == a0 && a1 != 1) {
Answer *= 2;
}
if (b1 == b0 && b1 != 1) {
Answer *= 2;
}
}
if (isok == false) {
Answer = 0;
}
cout << Answer << "\n";
}
return 0;
}
下面开始问答:
Q:Count是什么?
A:分解一个质数求得数量,并将其带入所需的变量,原数也会被改,这也是为什么加指针的原因
欢迎大家提问。