[HAOI2011]Problem b
题意
组询问,给定
, 求
并且
=
的数对数量。
()
解题思路
- 定义
表示
并且
满足
的数对数量。
容斥易得,本题的答案即是:
那么现在我们的目标是在 的时间内快速求出
考虑对于原式进行化简,原式即:
首先是把原式里面的 提出来:
下一步则是 转化为
:
又因为 : 等价于
&&
然后我们可以知道, 内的所有数中
的倍数一共有
个。所以式子进一步化简:
现在就可以整一个整除分块乱搞哩!1
#include <bits/stdc++.h>
using namespace std;
#define int long long
inline int read() {
int x = 0, flag = 1;
char ch = getchar();
for( ; ch > '9' || ch < '0' ; ch = getchar()) if(ch == '-') flag = -1;
for( ; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + ch - '0';
return x * flag;
}
const int MAXN = 1e5 + 500;
int Prime[MAXN], mu[MAXN],tot = 0;
bool book[MAXN];
int T,a,b,c,d,k;
void GetPrime() {
mu[1] = 1;
for(int i = 2 ; i <= 6e4 ; i ++) {
if(!book[i]) Prime[++ tot] = i, mu[i] = -1;
for(int j = 1 ; j <= tot ; j ++) {
if(Prime[j] * i > 6e4) break;
book[Prime[j] * i] = 1;
if(i % Prime[j] == 0) break;
mu[i * Prime[j]] = -mu[i];
}
}
for(int i = 1 ; i <= 6e4 ; i ++) mu[i] = mu[i - 1] + mu[i];
return ;
}
int calc(int a, int b) {
int Ans = 0;
int mx=a / k, my = b / k;
for(int l = 1 ,r ;l <= min (mx, my) ; l = r + 1) {
r = min(mx / (mx / l), my / (my / l));
Ans += (mx / l) * (my / l) * (mu[r] - mu[l - 1]);
}
return Ans;
}
signed main() {
GetPrime();
T = read();
while(T --) {
a = read(), b = read(), c = read(), d = read(); k = read();
printf("%lld\n", calc(b, d) - calc(b, c - 1) - calc(a - 1, d) + calc(a - 1, c - 1));
}
return 0;
} 
京公网安备 11010502036488号