數論、、gcd

RGCDQ

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1663    Accepted Submission(s): 701


Problem Description
Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more and more interesting things about GCD. Today He comes up with Range Greatest Common Divisor Query (RGCDQ). What’s RGCDQ? Please let me explain it to you gradually. For a positive integer x, F(x) indicates the number of kind of prime factor of x. For example F(2)=1. F(10)=2, because 10=2*5. F(12)=2, because 12=2*2*3, there are two kinds of prime factor. For each query, we will get an interval [L, R], Hdu wants to know maxGCD(F(i),F(j)) (Li<jR)
 

Input
There are multiple queries. In the first line of the input file there is an integer T indicates the number of queries.
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
 

Output
For each query,output the answer in a single line. 
See the sample for more details.
 

Sample Input
2 2 3 3 5
 

Sample Output
1 1
 

Author
ZSTU
 

Source
 

Recommend
wange2014


這題還不錯,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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章