!HDU 5317 求区间里两个数的质因数个数的gcd的最大值-预处理

题意:设一个数i的质因数个数为F(i),现给你一个区间[l~r],求max(F[i],F[j])  数据范围:10^6

分析:

预处理出所有的F[i],O(nlgn),10^6不会超时;然后查询用O(7),查询不能用O(n),因为有多个查询会超时。

区间问题减少查询时间复杂度多半类似一个区间的和用两个前缀和相减的方式,前缀和可以在预处理的时候计算,然后区间查询是用两个前缀和相减就行了。如sum[l~r]=sum[r]-sum[l-1],再比如之前的什么我想不起来一时,想起来加上。

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<set>
#include<vector>
using namespace std;
int t,vis[1000005];
int l,r;
int sum[1000005][10];
int cnt[1000005];
void init()
{
	memset(vis,0,sizeof(vis));
	memset(sum,0,sizeof(sum));
	memset(cnt,0,sizeof(cnt));
	for(int i=2;i<=1000000;i++){
		if(!vis[i]){
			for(int j=i;j<=1000000;j+=i){
				vis[j]=1;
				cnt[j]++;
			}
		}
	}
	for(int i=2;i<=1000000;i++){
		for(int j=1;j<8;j++){
			if(j==cnt[i]) sum[i][j]=sum[i-1][j]+1;
			else sum[i][j]=sum[i-1][j];
		}
	}
}
int main()
{
	init();
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&l,&r);
		int a[10];
		int ans;
		memset(a,0,sizeof(a));
		for(int i=1;i<8;i++){
			a[i]=sum[r][i]-sum[l-1][i];
		}
		if(a[7]>=2) ans=7;
		else if(a[6]>=2) ans=6;
		else if(a[5]>=2) ans=5;
		else if(a[4]>=2) ans=4;
		else if(a[3]>=2||a[6]!=0&&a[3]!=0) ans=3;
		else if(a[6]!=0&&a[4]!=0||a[6]!=0&&a[2]!=0||a[4]!=0&&a[2]!=0||a[2]>=2) ans=2;
		else ans=1;
		printf("%d\n",ans);
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-10 05:44:12

!HDU 5317 求区间里两个数的质因数个数的gcd的最大值-预处理的相关文章

hdu 1856 求集合里元素的个数 输出最大的个数是多少

求集合里元素的个数 输出最大的个数是多少 Sample Input41 23 45 61 641 23 45 67 8 Sample Output42 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # include <queue> 7 # define LL

均分纸牌(贪心求区间和为平均数的最多个数)

Description 有 N 堆纸牌,编号分别为 1,2,…, N.每堆上有若干张,但纸牌总数必为 N 的倍数.可以在任一堆上取若于张纸牌,然后移动. 移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上:在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上:其他堆上取的纸牌,可以移到相邻左边或右边的堆上. 现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多. 例如 N=4,4 堆纸牌数分别为: ① 9 ② 8 ③ 17 ④ 6 移动3次可达到目的: 从 ③

hdu 3074 求区间乘积

线段树水题 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; #define LL(x) (x<<1) #define RR(x) ((x<<1)|1) long long num[4*50000]; int update(int L,int R,int pos,int k,int mark) { if(L==pos&&R==p

HDU 4417.Super Mario-无修改区间小于等于H的数的个数-可持久化线段树

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9618    Accepted Submission(s): 4074 Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping ability

HDU 3473-Minimum Sum(划分树-求区间sigma最小值)

Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3710    Accepted Submission(s): 852 Problem Description You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you

hdu 5317 RGCDQ 多校 思维题

点击打开链接题目链接 RGCDQ Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 328    Accepted Submission(s): 164 Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find

tsinghua-6 质因数个数

就是求一个数的质因数个数,超时n次,束手无策, 查了题解,一秒解决, 喵. 要注意1既不是质数也不是合数. /********************** author: yomi date: 18.3.12 ps: **********************/ #include <iostream> #include <cmath> #include <cstdio> using namespace std; /* TLE -----> 超时原因大概就是还另外

HDU 4343 多查询求区间内的最大不相交区间个数-思维&amp;贪心-卡时间&amp;二分&amp;剪枝

题意:给你一些区间,现在有m个查询,求出每个查询的区间内的最大的不相交区间个数 分析: 几天前那道说谎问题时用dp的摞箱子模型求的最大的不相交区间个数,但是这题不能用这个方法,因为这题是动态的查询,不可能每个查询dp一次,超时. 这题用贪心策略.求区间[l~r]里的最大不相交区间,贪心策略就应该先选该区间内右端点最小的,这样给以后待选的区间留下更大的空间,所以我们的做法就是先按照区间的右端点排序,然后每次查询依次挑出查询区间里右端点最小的,并且把查询区间的左端点更新为刚才挑出的区间的右端点(这个

HDU 5327 区间里由不同的数字组成的数的个数-set-(枚举)

题意:形如12345是我们要找的数,形如11是不合法的数,找出区间[a~b]里的合法数的个数,1<=a<=b<=10^5 分析:预处理,枚举从1开始到i结束的区间的合法数的个数,然后输入一个区间就输出sum[b]-sum[a-1]即可.这里借助set工具,利用它的count()函数,枚举数i,判定它是否为合法的数,方法是取它的每一位,然后在set里对这一位计数,如果 !=0,说明set里已经有相同的数字了,那么这个数就不合法,否则就插入这一位的数字. STL大法好!要善于运用 代码: #