Problem b HYSBZ - 2301
對於給出的 個詢問,每次求有多少個數對 ,滿足 , ,且 , 函數爲 和 的最大公約數。
Input
第一行一個整數 ,接下來 行每行五個整數,分別表示
Output
共 行,每行一個整數表示滿足要求的數對 的個數
Sample Input
2
2 5 1 5 1
1 5 1 5 2
Sample Output
14
3
Hint
的數據滿足:
題解
題目求解
令
根據容斥的原理,我們可以知道
所以重點在於 的求法。
和以前一樣,令 。
因此也可以分塊計算。
代碼
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 10;
int mu[maxn], prime[maxn], cnt = 0;
bool vis[maxn];
void init() {
mu[1] = 1;
for (int i = 2; i < maxn; i++) {
if (vis[i] == false) {
prime[cnt++] = i;
mu[i] = -1;
}
for (int j = 0; j < cnt && i * prime[j] < maxn; j++) {
vis[i * prime[j]] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
for (int i = 2; i < maxn; i++) {
mu[i] += mu[i - 1];
}
}
int solve(int a, int b) {
int ans = 0;
if (a > b) swap(a, b);
for (int l = 1, r; l <= a; l = r + 1) {
r = min(a/(a/l), b/(b/l));
ans += (mu[r] - mu[l - 1]) * (a/l) * (b/l);
}
return ans;
}
int main()
{
init();
int n, a, b, c, d, k;
scanf("%d", &n);
while (n--) {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
printf("%d\n", solve(b/k, d/k) - solve(b/k, (c - 1)/k) - solve((a - 1)/k, d/k) + solve((a - 1)/k, (c - 1)/k));
}
return 0;
}
GCD HDU - 1695
Problem Description
Given integers: you’re to find in , in that . means the greatest common divisor of and . Since the number of choices may be very large, you’re only required to output the total number of different number pairs.
Please notice that, () and () are considered to be the same.
You can assume that in all test cases.
Input
The input consists of several test cases. The first line of the input is the number of the cases. There are no more than cases.
Each case contains five integers: , as described above.
Output
For each test case, print the number of choices. Use the format in the example.
Sample Input
2
1 3 1 5 1
1 11014 1 14409 9
Sample Output
Case 1: 9
Case 2: 736427
Hint
For the first sample input, all the pairs of numbers are .
題解
起始這題和上題差不多,一樣的容斥。但是不同的是在這題看來, 和 被看作是同樣的一對,只計數一次。
題目已經說明保證 。
所以我們只需要容斥進行這樣子的處理:
令 。
想想爲什麼?
因爲只有滿足 纔會有重複對的情況吧?
接下來對式子的處理也很容易。
代碼
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
int mu[maxn],prime[maxn], cnt = 0;
bool vis[maxn];
void init() {
mu[1] = 1;
for (int i = 2; i < maxn; i++) {
if (vis[i] == false) {
prime[cnt++] = i;
mu[i] = -1;
}
for (int j = 0; j < cnt && prime[j] * i < maxn; j++) {
vis[prime[j] * i] = true;
if (i % prime[j] == 0) {
mu[i * prime[j]] = 0;
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
for (int i = 2; i < maxn; i++) {
mu[i] += mu[i - 1];
}
}
LL solve(int a, int b) {
LL ans = 0;
for (int l = 1, r; l <= a; l = r + 1) {
r = min(a/(a/l), b/(b/l));
ans += (LL)(mu[r] - mu[l - 1]) * (a/l) * (b/l);
}
return ans;
}
int main()
{
init();
int a, b, c, d, k, n;
scanf("%d", &n);
for (int ca = 0; ca < n; ca++) {
scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);
if (k == 0) {
printf("Case %d: 0\n", ca + 1);
continue;
}
if (b > d) swap(b, d);
printf("Case %d: %lld\n", ca + 1, solve(b/k, d/k) - solve(b/k, b/k)/2);
}
return 0;
}