HDU 5317 RGCDQ (合数分解+预处理)
题目链接:HDU 5317 RGCDQ
题意:定义函数F(x)为x的不同的素因子且小于等于x的个数。询问[l,r]区间中gcd(F(i),F(j))的最大值。
思路:暴力预处理出全部的合数分解结果。发现F(x)最大也仅仅有7。之后就是暴力求出全部1到7出现次数的前缀和。询问的时候就打到O(1)了。
AC代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define MAXN 1000010 bool isPrime[MAXN+10]; int Prime[800000+10]; int sum[8][MAXN+10]; int d[MAXN+10]; int cnt=0; void init(){ int i,j; memset(isPrime,true,sizeof isPrime); isPrime[0]=isPrime[1]=false; for(i=2;i<=MAXN;i++){ if(!isPrime[i]) continue; Prime[cnt++]=i; for(j=i+i;j<=MAXN;j+=i) isPrime[j]=false; } } int slove(int x){ int i,ans; ans=0; for(i=0;Prime[i]*Prime[i]<=x && i<cnt;i++){ if(x%Prime[i]==0){ while(x%Prime[i]==0){ x/=Prime[i]; } ans++; } } if(x!=1) ans++; return ans; } void Pre(){ init(); int i,j; memset(sum,0,sizeof sum); memset(d,0,sizeof d); for(i=2;i<=MAXN;i++) { d[i]=slove(i);//f函数的值 } for(i=1;i<=7;i++){ for(j=1;j<=MAXN;j++){ if(d[j]==i) sum[i][j]=sum[i][j-1]+1; else sum[i][j]=sum[i][j-1]; //printf("%d:%d..",j,sum[i][j]); //getchar(); } } } int gcd(int x,int y){ if(y==0) return x; return gcd(y,x%y); } int main(){ Pre(); int t,l,r,i,j; scanf("%d",&t); while(t--){ scanf("%d %d",&l,&r); int ans=1; for(i=1;i<=7;i++){ for(j=1;j<=7;j++){ int a=sum[i][r]-sum[i][l-1]; int b=sum[j][r]-sum[j][l-1]; if(a==0 || b==0)//表示个数是0说明个数为i或j没有出现 continue; if(i!=j || a>=2){ ans=max(ans,gcd(i,j)); } } } printf("%d\n",ans); } return 0; } /* 4 9 1 100 1000 4 213 454 4 112 1111 4 5 1111 4 1111 11111 5 11111 111111 6 111111 999999 6 999991 1000000 3 */