题意:求n和m之间的所有数的素因子个数的最大gcd值。
分析:这题好恶心,看着就是一颗线段树,但本题有一定的规律,我也是后来才发现,我还没推出这个规律,就不说了,就用纯线段树解答吧。因为个点数都小于1000000所以素因子个数不会超过7个所以建一个线段树,最下面一层是每个节点的素因子个数为1,2,3,4,5,6,7的有多少个,父节点求和,最终查询的是n到m之间有多少个1,2,3,4,5,6,7然后存在就求一下gcd着最大就好了
本题最重要的时间和空间,显然线段数中的点不会很大,所以采用short类型
代码如下:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int gcd(int a,int b){
return (b==0)?a:gcd(b,a%b);
}
const int N=100000;
int prime[N]={0};
int num_prime=0;
bool isNotPrime[N]={1,1};
void su1(){
for(long i = 2 ; i < N ; i ++){
if(!isNotPrime[i])
prime[num_prime++]=i;
for(long j = 0 ; j < num_prime &&i*prime[j]<N ;j ++) {
isNotPrime[i * prime[j]] = 1;
if( !(i % prime[j]))break;
}
}
}
int prime_solve(int n){
int k=0;
for(int i=0;i<num_prime&&prime[i]*prime[i]<=n;i++){
// cout<<prime[i]<<endl;
if(n%prime[i]==0){
while(n%prime[i]==0){
n/=prime[i];
}
k++;
}
}
if(n!=1)k++;
return k;
}//素因子分解求n的素因子个数
short a[4000005][8];
void updat(int id,int j,int l,int r,int mid){
if(l==r){
a[mid][j]=1;
return;
}
int i=(l+r)>>1;
if(id<=i)updat(id,j,l,i,2*mid);
else updat(id,j,i+1,r,2*mid+1);
a[mid][j]=a[2*mid][j]+a[2*mid+1][j];
}
int sum[8];
void su(int l,int r,int mid,int ll,int rr){
if(l>=ll&&r<=rr){
for(int i=1;i<=7;i++)
sum[i]+=a[mid][i];
return;
}
int i=(l+r)>>1;
if(ll<=i)su(l,i,2*mid,ll,rr);
if(rr>i)su(i+1,r,2*mid+1,ll,rr);
}//建树,求和,这是重点
int main(){
memset(a,0,sizeof(a));
su1();
// for(int i=1;i<=100;i++){
// if(isNotPrime[i])
// cout<<i<<" "<<prime_solve(i)<<endl;;
// }
// cout<<endl;
for(int i=2;i<=1000005;i++){
int d=prime_solve(i);
updat(i,d,2,1000005,1);
}
int n,m;
int t;
cin>>t;
while(t--){
scanf("%d%d",&n,&m);
memset(sum,0,sizeof(sum));
su(2,1000005,1,n,m);
int ans=-1;
for(int i=1;i<=7;i++)
for(int j=1;j<=7;j++){
if(i==j){
if(sum[i]>1)ans=max(ans,gcd(i,j));
}
else{
if(sum[i]>0&&sum[j]>0)ans=max(ans,gcd(i,j));
}
}//这个地方就可以纯暴力了
printf("%d\n",ans);
}
return 0;
}