RGCDQ
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1663 Accepted Submission(s): 701
In the next T lines, each line contains L, R which is mentioned above.
All input items are integers.
1<= T <= 1000000
2<=L < R<=1000000
See the sample for more details.
這題還不錯,mark一下~
題意:F(x)表示數x的素因子個數,求區間[L,R]中max GCD(F(i),F(j)),(L<=i<j<=R)
分析:由於詢問次數T很大,所以對於每次詢問幾乎要O(1)的時間複雜度求出答案纔可以。然而要求max GCD(F(i),F(j)) 應該要遍歷L~R纔對,,但這樣必然超時。對於這種詢問次數非常大的題目,一般都是通過預處理記錄答案的。雖然L~R非常大,但是通常會有一些特性使得一個非常小的變量就可以遍歷所有答案,發現很多題都是這樣。。。這題通過觀察可知,F(x)非常小,最多隻有7。所以可以首先通過篩法算出F(i),然後用f[i][num]來記錄數2~i中num(1<=num<=7))的個數。預處理完這些後就可以在每次詢問中快速計算答案:首先答案只會是1~7,已知L、R就可知L~R中素因子個數1~7的個數,它們的gcd是很有限的幾個,全部手算也行。
code:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N = 1e6+10;
int F[N], f[N][8], cnt[8];
int main()
{
int T, L, R;
for(int i=2; i<N; i++) if(!F[i])
{
for(int j=i; j<N; j+=i)
F[j]++;
} //通過篩法算出所有F(x)
for(int i=2; i<N; i++)
{
cnt[F[i]]++; //素因子個數的個數
for(int j=1; j<=7; j++)
{
f[i][j] = cnt[j];
}
}
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &L,&R);
int vis[10]={0}, maxn = 1;
for(int i=2; i<=7; i++)
{
if(f[R][i]-f[L-1][i] >= 2) maxn = max(maxn,i);
else if(f[R][i]-f[L-1][i] >= 1) vis[i] = 1;
}
for(int i=2; i<=7; i++)
{
if(!vis[i]) continue;
for(int j=2; j<=7; j++)
{
if(!vis[j] || i == j) continue;
maxn = max(maxn,__gcd(i,j));
}
}
printf("%d\n", maxn);
}
return 0;
}