zoukankan      html  css  js  c++  java
  • P3312 [SDOI2014]数表

    题意描述:

    洛谷

    有一个 (n imes m) 的表格,第 (i) 行第 (j) 列的权值为 (sigma(gcd(i,j))) , 有 (Q) 组询问,每次问你一个 (n imes m) 的表格中,不大于 (a) 的数字之和。

    数据范围: (n,mleq 10^5, Qleq 2e4)

    前置芝士:

    1.线性筛约数个数

    (n = p_1^{k_1}p_2^{k_2}...p_n^{k_n}) , 那么 (sigma(n) = (1+p_1^1+p_1^2+..+p_1^{k_1})(1+p_2^1+p_2^2+...p_2^{k2}) ...)

    考虑维护一下两个数组:

    • (sd(i)) 表示 (i) 的约数个数和
    • (d(i)) 表示 (i) 的最小质因子的 ((1+p_1^1+p_1^2+..p_1^{k_1})) (实际上是个等比数列求和的形式)

    还是考虑分三种情况来考虑:

    • (i) 为质数,显然 (sd(i) = i+ 1) , (d(i) = i+1)

    • (i \% prime[j] eq 0) 的时候, (prime[j])(i imes prime[j]) 的最小质因子,那么

      (sd(i imes prime[j]) = sd(i) imes sd(prime[j]))

      (d(i imes prime[j]) = prime[j] + 1)

    • (i\% prime[j] = 0) 的时候,(i imes prime[j]) 的最小质因子次数为 (i) 的最小质因子次数加1。

      (sd(i imes prime[j]) = {sd(i)over d(i)} imes(d(i) imes prime[j]) + 1)

      (d(i imes prime[j]) = d(i) imes prime[j] + 1)

    然后在线性筛的时候分情况讨论即可。

    solution:

    我们要求的其实是:

    (displaystylesum_{i=1}^{n}sum_{j=1}^{m} sigma(gcd(i,j))[ sigma(gcd(i,j)) leq a])

    还是先枚举一下 (gcd) :

    (displaystylesum_{d=1}^{n} sigma(d)[sigma(d) leq a] sum_{i=1}^{n}sum_{j=1}^{m} [gcd(i,j) == d])

    先把 (gcd(i,j) == d) 反演掉:

    (displaystylesum_{d=1} ^{n}sigma(d) [sigma(d)leq a] sum_{i=1}^{nover d}sum_{j=1}^{mover d} [gcd(i,j) == 1])

    (displaystylesum_{d=1}^{n}sigma(d)[sigma(d) leq a] sum_{i=1}^{nover d}sum_{j=1}^{mover d} sum_{p|i,p|j}mu(p))

    (displaystylesum_{d=1}^{n}sigma(d) [sigma(d) leq a] sum_{p=1}^{nover d} mu(p) {nover {dp}} {mover dp})

    (dp)(Q) 可得:

    (displaystylesum_{Q=1}^{n} {nover Q}{mover Q} sum_{dmid Q} sigma(d)[sigma(d)leq a] mu({nover Q}))

    对于每组询问的话,我们很难直接做,考虑离线下来,按 (a) 从小到大排一下序。

    前面的那一坨可以用数论分块来解决,设 (displaystyle f(n) = sum_{dmid n} sigma(d) mu({nover d}))

    因为我们把询问按 (a) 从小到大排序,枚举询问时,(a) 的增大会使得一些 (sigma(d) leq a) ,这时候我们需要把他的贡献算上去。

    对于 (sigma(d)) 不难发现它会对他的倍数 (i imes d) 的贡献为 (sigma(d) mu(i))

    调和级数来枚举 (d) 的倍数,在拿个树状数组维护一下 $f(n) $ 前缀和即可。

    然后前面的整除分块,后面的就是 (f(r)-f(l-1)) ,在树状数组上查询即可。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define int long long
    const int p = (1<<31);
    const int N = 1e5+10;
    int cntq,maxn,tot,l = 1;
    int prime[N],mu[N],tr[N],omg[N],d[N],ans[N];
    bool check[N];
    struct QAQ
    {
        int w,id;
        QAQ(){}
        QAQ(int a,int b){id = a, w = b;}
    }e[N];
    struct node
    {
        int n,m,a,id;
    }q[N];
    inline int read()
    {
        int s = 0,w = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
        return s * w;
    }
    int lowbit(int x){return x & -x;}
    void chenge(int x,int val)
    {
        for(; x <= N-5; x += lowbit(x)) tr[x] += val;
    }
    int query(int x)
    {
        if(x == 0) return 0;
        int res = 0;
        for(; x; x -= lowbit(x)) res += tr[x];
        return res;
    }
    bool cmp(QAQ a,QAQ b)
    {
        return a.w < b.w;
    }
    bool comp(node a,node b)
    {
        return a.a < b.a;
    }
    void Add(int x)
    {
        for(int i = 1; i * e[l].id <= maxn; i++) chenge(i*e[l].id,omg[e[l].id] * mu[i]);
    }
    void YYCH()
    {
        mu[1] = 1; omg[1] = 1;
        for(int i = 2; i <= maxn; i++)
        {
            if(!check[i])
            {
                prime[++tot] = i;
                mu[i] = -1;
                omg[i] = i+1;
                d[i] = i+1;
            }
            for(int j = 1; j <= tot && i * prime[j] <= maxn; j++)
            {
                check[i * prime[j]] = 1;
                if(i % prime[j] == 0)
                {
                    mu[i * prime[j]] = 0;
                    d[i * prime[j]] = (d[i] * prime[j]) + 1;
                    omg[i * prime[j]] = (omg[i] / d[i]) * (d[i] * prime[j] + 1);
                    break;
                }
                else
                {
                    mu[i * prime[j]] = -mu[i];
                    d[i * prime[j]] = prime[j] + 1;
                    omg[i * prime[j]] = omg[i] * omg[prime[j]];
                }
            } 
        }
        for(int i = 1; i <= maxn; i++) e[i] = QAQ(i,omg[i]);
        sort(e+1,e+maxn+1,cmp);
    }
    int slove(int n,int m,int id)
    {
        int res = 0;
        while(l <= maxn && e[l].w <= q[id].a) Add(l), l++;
        for(int l = 1, r; l <= n; l = r+1)
        {
            r = min(n/(n/l),m/(m/l));
            res += (n/l) * (m/l) * (query(r)-query(l-1));
        }
        return res;
    }
    signed main()
    {
        cntq = read();
        for(int i = 1; i <= cntq; i++)
        {
            q[i].n = read();
            q[i].m = read();
            q[i].a = read();
            q[i].id = i;
            if(q[i].n > q[i].m) swap(q[i].n,q[i].m);
            maxn = max(maxn,q[i].n);
        }
        YYCH();
        sort(q+1,q+cntq+1,comp);
        for(int i = 1; i <= cntq; i++) ans[q[i].id] = slove(q[i].n,q[i].m,i);
        for(int i = 1; i <= cntq; i++) printf("%lld
    ",ans[i] % p);
        return 0;
    }
    
  • 相关阅读:
    android数据恢复
    UVA 690 Pipeline Scheduling
    2017 国庆湖南 Day4
    2017 国庆湖南 Day5
    2017 国庆湖南 Day6
    2017国庆 清北学堂 北京综合强化班 Day1
    2017 国庆湖南Day2
    bzoj 2962 序列操作
    UVA 818 Cutting Chains
    UVA 211 The Domino Effect
  • 原文地址:https://www.cnblogs.com/genshy/p/14387489.html
Copyright © 2011-2022 走看看