B - RGCDQ-HDU 5317-素数筛法

本文介绍了解决一道算法竞赛题目(HDU 5317)的方法,该题目要求计算区间内整数质因数种类的最大公约数。通过预处理质数表并统计每个数的质因数种类,利用前缀和技巧高效解答查询。


题意 f(x)是x能分解成的素数的种类,

http://acm.hdu.edu.cn/showproblem.php?pid=5317

先打素数表,再用素数筛选出每个数的种类

接下来 求任意区间的 元素对应的f(x)的最大公约数,----队友读漏了gcd,以为是求区间最大值,拍了个线段树-无用功....

因为答案显然 只有1 2 3 4 5 6 7...所以预处理记下左端到每个数字间有多少个1 2 3 4 5 6 7,即可,然后对区间[a,b]记录的1 2 3 4 5 6 7个数相减,即可得到区间之间有多少个1 2 3 4 5,然后判断一下就好

 


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#define MAX 1000005
#define inf 0x3f3f3f3f
using namespace std;
#define tree_size MAX*3
int max(int a,int b)
{
	if (a<b)
		return b;
	return a;
};
bool f[1000500]; 
int ans[1000500];  
int yue[1000500][8];  


int main()
{
	
	//素数打表  
	__int64 i,j;
	f[1]=true;
	
	for (i=2;i<=MAX;i++)    //1处
	{
		if (f[i]==false)           //优化
		{
			for (j=(__int64)i*i;j<=1000500;j=j+i)   // 如果1处用1000必须_int64强制转换
			{
				
				f[j]=true;
			}
		}
	} 
	
	
	for (i=2;i<=MAX;i++)    //1处
	{
		if (f[i]==false)
		{	
			for (j=i;j<=MAX;j=j+i)
			{
				ans[j]++;
			} 
		} 
	}
	
	for (i=1;i<=1000000;i++)
	{
		for (j=1;j<=7;j++)
			yue[i][j]=yue[i-1][j];
		yue[i][ans[i]]++;
	}
	
	
	
	int l,t,a,b;
	scanf("%d",&t);
    while(t--)
    {
		
		scanf("%d%d",&a,&b);
		int flag=0;
		for (j=7;j>=3;j--)
		{
			int tmp=yue[b][j]-yue[a-1][j];
			if (tmp>=2)
			{
				printf("%d\n",j);
				flag=1;
				break;
			}
		}
		if (flag) continue;
		
		int t1=yue[b][6]-yue[a-1][6];
		int t2=yue[b][3]-yue[a-1][3];
		
		if (t1+t2>=2)  
		{
			printf("3\n"); 
			continue;
		}
		else
		{
			t1=yue[b][2]-yue[a-1][2];
			t2=yue[b][4]-yue[a-1][4];
			int t3=yue[b][6]-yue[a-1][6];
			if (t1+t2+t3>=2)
			{ 
				printf("2\n");
				continue; 
			}
			else
				printf("1\n");
			
		}
			 
	
	
	
}


return 0;

}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
#define MAX 1000005
#define inf 0x3f3f3f3f
using namespace std;
#define tree_size MAX*3
int max(int a,int b)
{
	if (a<b)
		return b;
	return a;
};
bool f[1000500]; 
int ans[1000500];  
int yue[1000500][8];  


int main()
{
	
	//素数打表  
	__int64 i,j;
	f[1]=true;
	
	for (i=2;i<=MAX;i++)    //1处
	{
		if (f[i]==false)           //优化
		{
			for (j=(__int64)i*i;j<=1000500;j=j+i)   // 如果1处用1000必须_int64强制转换
			{
				
				f[j]=true;
			}
		}
	} 
	
	
	for (i=2;i<=MAX;i++)    //1处
	{
		if (f[i]==false)
		{	
			for (j=i;j<=MAX;j=j+i)
			{
				ans[j]++;
			} 
		} 
	}
	
	for (i=1;i<=1000000;i++)
	{
		for (j=1;j<=7;j++)
			yue[i][j]=yue[i-1][j];
		yue[i][ans[i]]++;
	}
	
	
	
	int l,t,a,b;
	scanf("%d",&t);
    while(t--)
    {
		
		scanf("%d%d",&a,&b);
		int flag=0;
		for (j=7;j>=3;j--)
		{
			int tmp=yue[b][j]-yue[a-1][j];
			if (tmp>=2)
			{
				printf("%d\n",j);
				flag=1;
				break;
			}
		}
		if (flag) continue;
		
		int t1=yue[b][6]-yue[a-1][6];
		int t2=yue[b][3]-yue[a-1][3];
		
		if (t1+t2>=2)  
		{
			printf("3\n"); 
			continue;
		}
		else
		{
			t1=yue[b][2]-yue[a-1][2];
			t2=yue[b][4]-yue[a-1][4];
			int t3=yue[b][6]-yue[a-1][6];
			if (t1+t2+t3>=2)
			{ 
				printf("2\n");
				continue; 
			}
			else
				printf("1\n");
			
		}
			 
	
	
	
}


return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值