• hdu 4676 Sum Of Gcd 莫队+数论


    题目链接

    给n个数, m个询问, 每个询问给出[l, r], 问你对于任意i, j。gcd(a[i], a[j]) L <= i < j <= R的和。

    假设两个数的公约数有b1, b2, b2...bn, 那么这两个数的最大公约数就是phi[b1] + phi[b2] + phi[b3]...+phi[bn]。

    知道这个就可以用莫队了, 具体看代码。

    #include <bits/stdc++.h>
    
    using namespace std;
    #define pb(x) push_back(x)
    #define ll long long
    #define mk(x, y) make_pair(x, y)
    #define lson l, m, rt<<1
    #define mem(a) memset(a, 0, sizeof(a))
    #define rson m+1, r, rt<<1|1
    #define mem1(a) memset(a, -1, sizeof(a))
    #define mem2(a) memset(a, 0x3f, sizeof(a))
    #define rep(i, n, a) for(int i = a; i<n; i++)
    #define fi first
    #define se second
    typedef pair<int, int> pll;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int mod = 7777777;
    const int inf = 1061109567;
    const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    const int maxn = 2e4+3;
    vector <int> v[maxn];
    struct node
    {
        int l, r, block, id;
    }q[maxn];
    bool cmp(const node& a, const node& b)
    {
        if(a.block == b.block)
            return a.r < b.r;
        return a.block < b.block;
    }
    int phi[maxn], cnt[maxn], a[maxn];
    ll res, ans[maxn];
    void add(int x)
    {
        for(int i = 0; i < v[x].size(); i++) {
            res += phi[v[x][i]]*(cnt[v[x][i]]++);
        }
    }
    void sub(int x)
    {
        for(int i = 0; i < v[x].size(); i++) {
            res -= phi[v[x][i]]*(--cnt[v[x][i]]);
        }
    }
    void solve(int m)
    {
        int L = 1, R = 0;
        res = 0;
        mem(cnt);
        for(int i = 0; i < m; i++) {
            while(R < q[i].r) {
                add(a[++R]);
            }
            while(R > q[i].r) {
                sub(a[R--]);
            }
            while(L < q[i].l) {
                sub(a[L++]);
            }
            while(L > q[i].l) {
                add(a[--L]);
            }
            ans[q[i].id] = res;
        }
    }
    void init()
    {
        for(int i = 1; i < maxn; i++) {
            phi[i] = i;
            for(int j = i; j < maxn; j += i) {
                v[j].pb(i);
            }
        }
        for(int i = 2; i < maxn; i++) {
            if(phi[i] == i) {
                for(int j = i; j < maxn; j += i) {
                    phi[j] = phi[j]/i*(i-1);
                }
            }
        }
    }
    int main()
    {
        init();
        int t, n, m;
        cin>>t;
        for(int casee = 1; casee <= t; casee++) {
            scanf("%d", &n);
            int BLOCK = sqrt(n*1.0);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
            }
            scanf("%d", &m);
            for(int i = 0; i < m; i++) {
                scanf("%d%d", &q[i].l, &q[i].r);
                q[i].block = q[i].l/BLOCK;
                q[i].id = i;
            }
            sort(q, q+m, cmp);
            solve(m);
            printf("Case #%d:
    ", casee);
            for(int i = 0; i < m; i++) {
                printf("%lld
    ", ans[i]);
            }
        }
    }
  • 相关阅读:
    微软VS2008月底推出beta 2中文版 搭配.NET 3.5
    Asp.Net AjaxPasswordstrength控件使用
    Asp.Net AjaxHoverMenu控件使用
    Asp.Net Ajax AutoComplete控件使用
    ASP.NET中基类页的设计和使用
    Asp.Net中页面间传值方法
    基于ASP.NET AJAX技术开发在线RSS阅读器(上篇)
    Asp.Net AjaxFilteredTextBox控件使用
    基于ASP.NET AJAX技术开发在线RSS阅读器(下篇)
    Asp.Net AjaxTextBoxWateramrk控件使用
  • 原文地址:https://www.cnblogs.com/yohaha/p/5682670.html
Copyright © 2020-2023  润新知