#include <cstdio>
#include <cstring>
using namespace std;
bool primes[1000001];
int primesV[1000001];
int priSize;
int sets[1000001];
void GetPrimes() {
int i;
priSize = 0;
memset(primes, true, sizeof(primes));
for (i = 2; i < 1000000; ++i) {
if (primes[i]) {
primesV[priSize++] = i;
for (int j = 2; j * i <= 1000000; ++j) {
primes[i * j] = false;
}
}
}
}
int FindSet(int n) {
if (sets[n] == n) {
return n;
}
return sets[n] = FindSet(sets[n]);
}
void UnionSet(int a, int b) {
sets[FindSet(a)] = FindSet(b);
}
long long A, B, C, P;
int cas;
int main () {
freopen("B-large-practice.in", "r", stdin);
freopen("B-large-practice.out", "w", stdout);
scanf("%lld", &C);
cas = 0;
GetPrimes();
while (C--) {
cas++;
scanf("%lld %lld %lld", &A, &B, &P);
for (int i = 0; i <= B - A; ++i) {
sets[i] = i;
}
long long prime;
for (int i = 0; i < priSize; ++i) {
prime = primesV[i];
if (prime >= P) {
long long st = (A + prime - 1) / prime * prime;
long long step = st + prime;
while (step <= B) {
UnionSet(step - A, st - A);
step += prime;
}
}
}
int sum = 0;
for (int i = 0; i <= B - A; ++i) {
if (FindSet(i) == i) {
++sum;
}
}
printf("Case #%d: %d\n", cas, sum);
}
return 0;
}
官方解析:
Firstly, we only need to find prime factors less than the size of the interval.
If a prime is larger than or equal to the size of the interval,
then at most one integer in the interval can have that prime as a factor,
so it will never be used to merge sets.
(由于做题时,没有分析出这个结论,导致large数据的题解没做出来。
这个结论限制了,只需求出0-1000000之间的素数即可。)
题义: 只要两个数有一个公约数,且公约数为数素并一个大于P,那么这两个数就可以分为一个集合,
比如 P为5, 那么 10, 15, 20就为一个集合 ,因为他们的素公约数为5满足条件。
而12,18不是一个集合,他们的素公约数为3, 小于P。
Small dataset
1 <= C <= 10 1 <= A <= B <= 1000 2 <= P <= B
Large dataset
1 <= C <= 100 1 <= A <= B <= 1012
B <= A + 1000000 2 <= P <= B
Sample
Input | Output |
2 | Case #1: 9 |