J - GCD(rmq+二分)

点击打开链接

 

题目大概说给一个包含n个数的序列,多次询问有多少个区间GCD值等于某个区间的gcd值。

任何一个区间不同的GCD个数是log级别的,因为随着右端点向右延伸GCD是单调不增的,而每次递减GCD至少除以2。

考虑固定左端点,最多就nlogn种GCD,可以直接把所有区间GCD值预处理出来,用map存储各种GCD值的个数,查询时直接输出。

具体是这样处理的:枚举左端点,进行若干次二分查找,看当前GCD值最多能延伸到哪儿,进而统计当前GCD值的数量。

而求区间GCD,用ST表,预处理一下,就能在O(1)时间复杂度求出任意区间的gcd了。

#include
#include
#include
#include
#include
const int maxn = 100005;
const int maxlog = 17;

using namespace std;
int n;
int gcd(int a,int b)
{
    while(b)
    {
        int t=b;
        b=a%b;
        a=t;
    }
    return a;
}
struct RMQ //用于求区间最值
{
    int d[maxn][maxlog];
    void init(const int * A, int n) //被求最值的数组,数组的大小
    {
        //int n = A.size();
        for(int i = 1; i <= n; i++)
            d[i][0] = A[i];
        for(int j = 1; (1<>t;
    int a[100005],cse=1;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        rmq.init(a,n);
        maprec;
        for(int i=1;i<=n;i++)
        {
            int g=a[i],j=i;
            while(j<=n)
            {
                int l=j,r=n;
                while(l>q;
        while(q--)
        {
            cin>>a>>b;
            int g=rmq.query(a,b);
            printf("%d %lld\n",g,rec[g]);
        }
    }
}

 

 

 

你可能感兴趣的:(姗姗杯,算法)