【题意】定义f(i)表示把i分解成质因素中有多少个不同的素数,求出(l,r)中任意两个f(i)的GCD的最大值。
【分析】求出1~10^6所有数的f(i),和分解质因素求法一样,筛出所有素数;然后发现f(i)在1~7之间,那么好办了,可以用线段树存1~7每个数出现的次数,最后答案查出来后暴力算下最大的GCD(最多只有7种数,暴力就行了)。这样复杂度T*logn*7。线段树中的sum用int超内存了,改成shot才行。内存卡的好紧。
【AC CODE】1357ms
#include <cstdio> #include <cstring> #include <cctype> #include <cmath> #include <set> //#include <unordered_set> #include <queue> #include <stack> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long LL; #define rep(i,a,n) for(int i = a; i < n; i++) #define repe(i,a,n) for(int i = a; i <= n; i++) #define per(i,n,a) for(int i = n; i >= a; i--) #define clc(a,b) memset(a,b,sizeof(a)) const int INF = 0x3f3f3f3f, MAXN = 1000000+10, MAXNUM = 1000000,MAXOUT = MAXN/10; char buf[MAXN], *ps = buf, *pe = buf+1; inline void rnext(){ if(++ps == pe) pe = (ps = buf)+fread(buf,1,sizeof(buf),stdin); } template <class T> inline bool in(T &ans) { ans = 0; T f = 1; if(ps == pe) return false;//EOF do{ rnext(); if('-' == *ps) f = -1; }while(!isdigit(*ps) && ps != pe); if(ps == pe) return false;//EOF do { ans = (ans<<1)+(ans<<3)+*ps-48; rnext(); }while(isdigit(*ps) && ps != pe); ans *= f; return true; } char bufout[MAXOUT], outtmp[50],*pout = bufout, *pend = bufout+MAXOUT; inline void write()/*必须在程序结束时加 write()*/ { fwrite(bufout,1,pout-bufout,stdout); pout = bufout; } inline void out_char(char c){ *(pout++) = c;if(pout == pend) write();} inline void out_str(char *s) { while(*s) { *(pout++) = *(s++); if(pout == pend) write(); } } template <class T> inline void out_int(T x) { if(!x) { out_char('0'); return; } if(x < 0) x = -x,out_char('-'); int len = 0; while(x) { outtmp[len++] = x%10+48; x /= 10; } outtmp[len] = 0; for(int i = 0, j = len-1; i < j; i++,j--) swap(outtmp[i],outtmp[j]); out_str(outtmp); } int prime[MAXN+10]; bool isprime[MAXN+10]; void get_prime() { memset(isprime,1,sizeof(isprime)); int len = sqrt(MAXNUM+0.5); repe(i,2,len) { if(!isprime[i]) continue; for(int j = i*i; j <= MAXNUM; j += i) isprime[j] = false; } } void getprime() { clc(prime,0); for (int i = 2; i <= MAXNUM; i++) { if (!prime[i])prime[++prime[0]] = i; for (int j = 1; j <= prime[0] && prime[j] <= MAXNUM/i; j++) { prime[prime[j]*i] = 1; if (i%prime[j] == 0) break; } } } int kind(int x) { if(isprime[x]) return 1; int ans = 0; repe(j,1,prime[0]) { bool in = false; while(x && 0 == x%prime[j]) x /= prime[j], in = true; ans += in; if(isprime[x]) { if(x > 1 && x != prime[j]) ans++; break; } } return ans; } int f[MAXN]; short sum[MAXN<<1][7]; inline int id(int x, int y){return x+y|x!=y;} void bulid(int x, int y) { if(x == y) { sum[id(x,y)][f[x]-1] = 1; return; } int m = (x+y)>>1; bulid(x,m); bulid(m+1,y); int u = id(x,y),l = id(x,m),r = id(m+1,y); rep(i,0,7) { sum[u][i] = sum[l][i]+sum[r][i]; if(sum[u][i] >= 2) sum[u][i] = 2; } } int cnt[7]; void query(int x, int y, int ql, int qr) { if(ql <= x && y <= qr) { int u = id(x,y); rep(i,0,7) cnt[i] += sum[u][i]; return; } int m = (x+y)>>1; if(ql <= m) query(x,m,ql,qr); if(qr > m) query(m+1,y,ql,qr); } int gcd(int a, int b) { while(b){ a %= b; if(a < b) swap(a,b); } return a; } int get_ans() { per(i,6,0) if(cnt[i] >= 2) return i+1; vector<int> tmp; rep(i,0,7) if(cnt[i]) tmp.push_back(i+1); int mx = 1; rep(i,0,tmp.size()) { rep(j,i+1,tmp.size()) mx = max(mx,gcd(tmp[i],tmp[j])); } return mx; } int main() { #ifdef SHY freopen("d:\\1.txt", "r", stdin); #endif get_prime(); getprime(); repe(i,2,MAXNUM) f[i] = kind(i); bulid(2,MAXNUM); int t; in(t); while(t--) { int x,y; in(x);in(y); clc(cnt,0); query(2,MAXNUM,x,y); out_int(get_ans()); out_char('\n'); } write(); return 0; }