HDU OJ 5317 RGCDQ( 2015多校联合训练第3场) 暴力打表+小技巧

题目连接:Click here

题意:在一个[L,R]内找到最大的gcd(f[i],f[j])其中L<=if[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]就是这个区间f[x]出现次数>=2次的中取最大的f[x]。具体看代码。

 1 #include 
 2 #include 
 3 #include  
 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 )
20         {
21             f[j*i]++;
22         }
23     }
24     dp[2][1] = 1;
25     for(int i=3; 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 = 1;
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 }

 

转载于:https://www.cnblogs.com/TaoTaoCome/p/4685395.html

你可能感兴趣的:(HDU OJ 5317 RGCDQ( 2015多校联合训练第3场) 暴力打表+小技巧)