[HAOI2011]Problem b
Description
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
Input
第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
Output
共n行,每行一个整数表示满足要求的数对(x,y)的个数
Sample Input
2 2 5 1 5 1 1 5 1 5 2
Sample Output
143
Answer
#include
#define maxn (50000 + 10)
using namespace std;
typedef long long int LLI;
bool isPrime[maxn];
LLI primeList[maxn],primeCount = 0;
short Mob[maxn];
LLI sum[maxn];
void Mobius(LLI n) {
memset(isPrime,true,sizeof(isPrime));
isPrime[0] = false;
isPrime[1] = false;
Mob[1] = 1;
for(int i = 2; i <= n; i ++) {
if(isPrime[i]) {
primeCount ++;
primeList[primeCount] = i;
Mob[i] = -1;
}
for(int j = 1; j <= primeCount; j ++) {
if(i * primeList[j] > n) break;
isPrime[i * primeList[j]] = false;
if(!(i % primeList[j])) {
Mob[i * primeList[j]] = 0;
break;
} else Mob[i * primeList[j]] = -Mob[i];
}
}
}
LLI solve(int n,int m) {
if(n > m) swap(n,m);
LLI ans = 0;
for(int i = 1,la = 0; i <= n; i = la + 1) {
la = min(n / (n / i),m / (m / i));
ans += (LLI)(sum[la] - sum[i - 1]) * (n / i) * (m / i);
}
return ans;
}
int main() {
// freopen("in.txt","r",stdin);
int t;
Mobius(maxn);
for(int i = 1; i <= maxn; i ++) sum[i] = sum[i - 1] + Mob[i];
scanf("%d",&t);
while(t --) {
int a,b,c,d,k;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
LLI re = solve(b / k,d / k) + solve((a - 1) / k,(c - 1) / k);
re = re - solve(b / k,(c - 1) / k) - solve((a - 1) / k,d / k);
printf("%lld\n", re);
}
return 0;
}