您的位置:首页 > 其它

bzoj 2301 Problem b - 莫比乌斯反演

2017-07-24 22:19 260 查看

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

Output

共n行,每行一个整数表示满足要求的数对(x,y)的个数

Sample Input

2
2 5 1 5 1
1 5 1 5 2

Sample Output

14
3

HINT

100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

  题目大意 (如此简洁的题目就不需要我的烂文笔了)

  这是在迎接codeforces div 2一场蓝(灰)之前恭迎的最后的一道水题(一个名为Doggu的数论神犇这么说的)。好了,废话不多说了。

  如果你还没有做过bzoj 1101,那你应该赶紧做一下咯。

  推理和它一毛一样,然后你发现它求的实际上等于一个二维前缀和,于是它便真地成了一道水题了(你基本上不用改动什么,copy过来,二维前缀和加加减减就水掉了)。

Code

/**
* bzoj
* Problem#2301
* Accepted
* Time:14640ms
* Memory:1576k
*/
#include <iostream>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <list>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean;
const signed int inf = (signed)((1u << 31) - 1);
const signed long long llf = (signed long long)((1ull << 61) - 1);
const double eps = 1e-6;
const int binary_limit = 128;
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
#define max3(a, b, c) max(a, max(b, c))
#define min3(a, b, c) min(a, min(b, c))
template<typename T>
inline boolean readInteger(T& u){
char x;
int aFlag = 1;
while(!isdigit((x = getchar())) && x != '-' && x != -1);
if(x == -1) {
ungetc(x, stdin);
return false;
}
if(x == '-'){
x = getchar();
aFlag = -1;
}
for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
ungetc(x, stdin);
u *= aFlag;
return true;
}

const int limit = 5e4;

int n;
int num = 0;
int prime[10000];
int miu[limit + 1];
boolean vis[limit + 1];

inline void Euler() {
memset(vis, false, sizeof(vis));
miu[0] = 0, miu[1] = 1;
for(int i = 2; i <= limit; i++) {
if(!vis[i])    miu[i] = -1, prime[num++] = i;
for(int j = 0; j < num && prime[j] * 1LL * i <= limit; j++) {
int c = prime[j] * i;
vis[c] = true;
if((i % prime[j]) == 0) {
miu[c] = 0;
break;
} else {
miu[c] = -1 * miu[i];
}
}
miu[i] += miu[i - 1];
}
}

inline void init() {
readInteger(n);
}

inline long long calc(int a, int b, int d) {
long long ret = 0;
a /= d, b /= d;
if(a == 0 || b == 0)    return 0;
if(a > b)    swap(a, b);
ret = 0;
for(int i = 1, j; i <= a; i = j + 1) {
j = min(a / (a / i), b / (b / i));
ret += (a / j) * 1LL * (b / j) * (miu[j] - miu[i - 1]);
}
return ret;
}

inline void solve() {
int a, b, c, d, e;
while(n--) {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
printf(Auto"\n", calc(b, d, e) - calc(a - 1, d, e) - calc(c - 1, b, e) + calc(a - 1, c - 1, e));
}
}

int main() {
Euler();
init();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: