点击打开链接题目链接
2 2 3 3 5
1 1
给出l,r求在l,r中任意f(i)和f(j)的gcd的最大值
预处理出所有素数 和所有数的f
用s[i][j]代表j数之前f值为i的个数
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 1111111
using namespace std;
bool is_prime[MAXN];
int prime[MAXN];
int f[MAXN];
int s[10][MAXN];
void init1(){
    int p=1;
    for(int i=0;i<=MAXN;i++)
        is_prime[i]=1;
    is_prime[0]=is_prime[1]=0;
    for(int i=2;i<=MAXN;i++){
        if(is_prime[i]){
            prime[p++]=i;
            for(int j=2*i;j<=MAXN;j+=i)
                is_prime[j]=0;
        }
    }
}
int getfact(int x){
    int ans=0;
    for(int i=1;prime[i]*prime[i]<=x;i++){
        if(x%prime[i]==0){
            ans++;
            while(x%prime[i]==0)
                x/=prime[i];
            if(is_prime[x]){
                ans++;
                break;
            }
        }
    }
    return ans;
}
void init2(){
    memset(s,0,sizeof(s));
    s[1][2]=1;
    for(int i=1;i<=MAXN;i++){
        for(int j=1;j<=7;j++){
            if(j!=f[i])
                s[j][i]=s[j][i-1];
            else s[j][i]=s[j][i-1]+1;
        }
    }
}
int gcd(int a,int b){
    if(b==0)
        return a;
    return gcd(b,a%b);
}
int main(){
    init1();
    for(int i=2;i<=MAXN;i++){
        if(is_prime[i])
            f[i]=1;
        else
            f[i]=getfact(i);
    }
    init2();
    int l,r;
    int t;
    scanf("%d",&t);
    int cnt[10];
    while(t--){
        scanf("%d %d",&l,&r);
        l--;
        for(int i=1;i<=7;i++){
            cnt[i]=s[i][r]-s[i][l];
        }
        int ans=0;
        for(int i=7;i>=1;i--){
            if(cnt[i]>=2){
                ans=i;
                break;
            }
        }
        for(int i=1;i<=7;i++){
            if(cnt[i]){
                for(int j=i+1;j<=7;j++){
                    if(cnt[j]){
                        ans=max(ans,gcd(i,j));
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/qq_16843991/article/details/47110333