題目連接:戳ME
題意:在一個[L,R]內找到最大的gcd(f[i],f[j])其中L<=i<j<=R,f[x]表示i分解質因數後因子的種類數。eg:f[10]=2(10=2*5),f[12]=2(12=2*2*3)。
分析:很容易想到先將f[x]求出來,這裡x最大1e6,要在常數時間內求出f[x]。並且稍加分析就知道1<=f[x]<=7,可以用一個dp[i][j]表示從f[1]到f[i]有多少個j。這樣就可以在常數時間內預處理出來,後面在O(1)的時間內就可以輸出結果。並且這個題並不用把GCD求出來,區間裡最大的f[x]就是這個區間出現次數>=2次的最大的f[x]。具體看代碼。
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #define clc(a, b) memset(a, b, sizeof(a))
5 using namespace std;
6 const int M = 1e6+5;
7 int dp[M][8];
8 int f[M];
9
10 void Pre() // 預處理函數,
11 {
12 memset( dp, 0, sizeof(dp) );
13 memset( f, 0, sizeof(f) );
14 for( int i = 2; i < M; i++ ) // 首先將f(x)求出來,保存在f[]數組中
15 {
16 if( f[i] )
17 continue;
18 f[i] = 1;
19 for( int j=2; j*i<M; j++ )
20 {
21 f[j*i]++;
22 }
23 }
24 dp[2][1] = 1;
25 for(int i=3; i<M; i++) // 預處理dp[]數組
26 {
27 for(int j=1; j <= 7; j++)
28 {
29 dp[i][j] = dp[i-1][j];
30 }
31 dp[i][f[i]]++;
32 }
33 }
34
35 int main()
36 {
37 Pre();
38 int t;
39 scanf("%d", &t);
40 while( t-- )
41 {
42 int a, b;
43 scanf("%d %d", &a, &b);
44 int ret = 0;
45 for( int i=1; i<8; i++ )
46 { //保證i出現2次 //保證i出現過
47 if( dp[b][i]-dp[a-1][i] > 1 && dp[b][i] )
48 ret = max( ret, i );
49 }
50 printf("%d\n", ret);
51 }
52 }