zoukankan      html  css  js  c++  java
  • [BZOJ2301][HAOI2011]Problem b

    [BZOJ2301][HAOI2011]Problem b

    试题描述

    对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

    输入

    第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

    输出

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

    输入示例

    2
    2 5 1 5 1
    1 5 1 5 2

    输出示例

    14
    3

    数据规模及约定

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

    题解

    这就是最经典的莫比乌斯反演了。首先 [a, b][c, d](表示 x 属于第一个区间,y 属于第二个区间)的答案可以表示成 [1, b][1, d] - [1, a-1][1, d] - [1, b][1, c-1] + [1, a-1][1, c-1] 这个形式。

    接下来就是求下面这个 f(n, m, k) 了。

    最后按照 [n / (kd)][m / (kd)] 分类,O(sqrt(n)) 回答询问即可。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 50010
    #define LL long long
    
    int prime[maxn], cp, mu[maxn], smu[maxn];
    bool vis[maxn];
    void init() {
    	mu[1] = smu[1] = 1;
    	for(int i = 2; i < maxn; i++) {
    		if(!vis[i]) prime[++cp] = i, mu[i] = -1;
    		for(int j = 1; i * prime[j] < maxn && j <= cp; j++) {
    			vis[i*prime[j]] = 1;
    			if(i % prime[j] == 0){ mu[i*prime[j]] = 0; break; }
    			mu[i*prime[j]] = -mu[i];
    		}
    		smu[i] = smu[i-1] + mu[i];
    	}
    	return ;
    }
    
    LL f(int n, int m, int k) {
    	LL ans = 0;
    	n /= k; m /= k;
    	for(int i = 1, lst; i <= min(n, m); i = lst + 1) {
    		lst = min(n / (n / i), m / (m / i));
    		ans += (LL)(n / i) * (m / i) * (smu[lst] - smu[i-1]);
    	}
    	return ans;
    }
    
    int main() {
    	init();
    	int T = read();
    	while(T--) {
    		int a = read(), b = read(), c = read(), d = read(), k = read();
    		printf("%lld
    ", f(b, d, k) - f(a - 1, d, k) - f(b, c - 1, k) + f(a - 1, c - 1, k));
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    redis中save和bgsave区别
    scrapy生成json中文为ASCII码解决
    mysql数据库,创建只读用户
    memcached命令行、Memcached数据导出和导入
    Memcache 查看列出所有key方法
    Elasticsearch5.x 引擎健康情况
    docker容器创建MariaDB镜像
    大文本数据排序
    换行符 和回车符
    索引与文本文件
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7107634.html
Copyright © 2011-2022 走看看