ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

牛客小白月赛39 G. 冷静(树状数组/线性筛)

2021-10-23 17:03:27  阅读:200  来源: 互联网

标签:39 ch 10000005 int 询问 牛客 num 读入 小白月赛


链接:https://ac.nowcoder.com/acm/contest/11216/G
来源:牛客网

题目描述

想去实现宏大的梦想 向着那遥不可及的地方

想在那一片纯白的世界 留下我最初的脚印

在世界的终端 太阳在永不停息地运转

南风终将吹过小岛 轻抚我的柔发

想去实现心底小小的梦

——《ハルカトオク》

痛定思痛,奋楫争先再出发……

q 次询问。每次询问给定 n 和 K,问 1 ~ n 中有多少数可以表示为大于等于 K 的质数的乘积(一个数可以乘多次)。

输入描述:

第一行读入一个整数q 
接下来q行每行读入2个整数,第i行表示 niniKiKi
1≤q≤3e61≤q≤3e6,1≤ni,Ki≤3e61≤ni,Ki≤3e6。

输出描述:

q行,共 q 个数,分别表示 q 次询问的答案。

示例1

输入

复制

1
100 5

输出

复制

32

示例2

输入

复制

2
20 3
10 5

输出

复制

9
2

暴力做法就是把每个数唯一分解掉,每个查询暴力统计。考虑如何优化。首先,1到n每个数的最小质因子可以通过线性筛\(O(n)\)地求出来,但是这样对于每次查询的复杂度也是\(O(n)\)的,需要继续优化。因为整体值域比较小,可以借助树状数组维护,离线处理询问。具体来说,首先读入所有的询问并按照n从小到大进行排序并处理,然后维护一个变量num,每处理到一个询问,当num小于这个询问的k值的时候就不断把num这个数的最小质因子插入树状数组维护的桶然后把num++。最后\(O(log(n))\)查询答案并更新到答案数组。

注意这个题卡了一波cout

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int prime[10000005], primesize, phi[10000005], mn[10000005];
bool isprime[10000005];
int read() {
    int s=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
    return s*w;
}
void getlist(int listsize) {
    for(int i = 1; i <= 3000002; i++) isprime[i] = 1, mn[i] = 0x3f3f3f3f;
    isprime[1] = false;
    for(int i = 2; i <= listsize; i++) {
        if(isprime[i]) prime[++primesize] = i, mn[i] = i;
         for(int j = 1; j <= primesize && i * prime[j] <= listsize; j++) {
            isprime[i * prime[j]] = false;
            mn[i * prime[j]] = min(mn[i * prime[j]], prime[j]);
            if(i % prime[j] == 0) break;
        }
    }
}
struct ask {
	int n, k, id;
	bool operator < (const ask& o) const {
		return n < o.n;
	}
};
int ans[3000005];
int b[3000005];
void modify(int x, int y) {
	for(; x <= 3000000; x += (x & -x)) {
		b[x] += y;
	}
}
int query(int x) {
	int ans = 0;
	for(; x; x -= (x & -x)) {
		ans += b[x];
	}
	return ans;
}
int main() {

	getlist(3000000);
	int q;
	cin >> q;
	vector<ask> v;
	for(int i = 1; i <= q; i++) {
		int n, k;
		n = read(), k = read();
		ask tmp = {n, k, i};
		v.push_back(tmp);
	}
	sort(v.begin(), v.end());
	int num = 2;
	for(auto a : v) {
		while(num <= a.n) {
			modify(mn[num], 1);
			num++;
		}
		ans[a.id] = query(a.n) - query(a.k - 1);
	}
	for(int i = 1; i <= q; i++) {
		printf("%d\n", ans[i]);
	}
	return 0;
}

标签:39,ch,10000005,int,询问,牛客,num,读入,小白月赛
来源: https://www.cnblogs.com/lipoicyclic/p/15448941.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有