• Codeforces475D


    Portal

    Description

    给出长度为(n(nleq10^5))的序列({a_n}),给出(q(qleq3 imes10^5))(x),对于每个(x),求满足(gcd{a_L...a_R})的数对((L,R))有多少个。

    Solution

    (f[i][x])表示以(i)为左端点的区间中,(gcd=x)的有多少个。
    由右到左进行转移,赋初值(f[i][a_i]=1):$$f[i][gcd(x,a_i)]=sum f[i+1][x]$$因为对于以(a_i)为左端点的区间(gcd),最多只有(loga_i)种取值(每次(gcd)至少减小一半),所以第二维其实只有(loga_i)个有值。我们可以用map代替第二维,并滚动第一维。

    时间复杂度(O(nlog^2n))

    Code

    //CGCDSSQ
    #include <cstdio>
    #include <map>
    using namespace std;
    int const N=1e5+10;
    int n,m,a[N];
    map<int,long long> ans,f[2];
    map<int,long long>::iterator it;
    int gcd(int x,int y) {return x%y?gcd(y,x%y):y;}
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        int c=0;
        f[0][a[n]]=1; ans[a[n]]++;
        for(int i=n-1;i>=1;i--)
        {
            c^=1; f[c].clear(); f[c][a[i]]=1;
            for(it=f[c^1].begin();it!=f[c^1].end();it++)
                f[c][gcd(it->first,a[i])]+=it->second;
            for(it=f[c].begin();it!=f[c].end();it++) ans[it->first]+=f[c][it->first];
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int x; scanf("%d",&x);
            printf("%lld
    ",ans[x]);
        }
        return 0;
    }
    

    P.S.

    “以(a_i)为左端点的区间(gcd),最多只有(loga_i)种取值”感觉这个结论还蛮有用的。
    第一次用map,感觉好厉害!Σ(゚∀゚ノ)ノ

  • 相关阅读:
    ECMAScript2017之async function
    ES3之closure ( 闭包 )
    RxJS之AsyncSubject
    RxJS之BehaviorSubject
    RxJS之Subject主题 ( Angular环境 )
    RxJS之工具操作符 ( Angular环境 )
    RxJS之转化操作符 ( Angular环境 )
    RxJS之过滤操作符 ( Angular环境 )
    RxJS之组合操作符 ( Angular环境 )
    关于Qt的StyleSheet作用范围
  • 原文地址:https://www.cnblogs.com/VisJiao/p/8494287.html
Copyright © 2020-2023  润新知