zoukankan      html  css  js  c++  java
  • bzoj 3994 [SDOI2015]约数个数和

    题目链接

    题意很好理解。

    参考博客  https://blog.sengxian.com/solutions/bzoj-3994

    下边再说一下思路。

      首先,借助约数定理证明

      然后借助莫比乌斯函数的性质及一系列的求和顺序变换,得到

      最后定义D(x)为d(x)的前缀和,那么最后那个式子可以化为 sigma mu[x]*D[n/x]*D[m/x]      (x=1…min(n,m)),这时就可以借助分块+预处理前缀和的方法来求ans了。

      ps. 因为d[x]是积性函数,所以可以用线性筛来处理。

    for (int i=1, last=1; i<=n; i=last+1)
    {
        last = min(n / (n / i), m / (m / i));
        ans += (LL)(sum[last] - sum[i - 1]) * (n / i) * (m / i);
    }
    分块+预处理前缀和模板
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    
    const int maxn=5e5+5;
    int prime[maxn+5];
    bool check[maxn+5];
    int d[maxn+5];
    int mu[maxn+5];
    LL D[maxn+5];
    int MU[maxn+5];
    int min_prime_cnt[maxn+5];
    
    void init()
    {
        mu[1]=1,d[1]=1;
        int tot=0;
        for(int i=2; i<=maxn; i++)
        {
            if(!check[i])
            {
                prime[tot++]=i;
                mu[i]=-1;
                min_prime_cnt[i]=1;
                d[i]=2;
            }
            for(int j=0; j<tot; j++)
            {
                int t=i*prime[j];
                if(t>maxn) break;
                check[t]=true;
                if(i%prime[j]==0)
                {
                    mu[t]=0;
                    min_prime_cnt[t]=min_prime_cnt[i]+1;
                    d[t]=d[i]/(min_prime_cnt[i]+1)*(min_prime_cnt[t]+1);
                    break;
                }
                else
                {
                    mu[t]=-mu[i];
                    d[t]=d[i]*2;
                    min_prime_cnt[t]=1;
                }
            }
        }
        for(int i=1; i<=maxn; i++)
        {
            MU[i]=MU[i-1]+mu[i];
            D[i]=D[i-1]+d[i];
        }
    }
    
    int n,m;
    
    int main()
    {
        init();
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            LL ans=0;
            for (int i=1, last=1; i<=min(n,m); i=last+1)
            {
                last = min(n / (n / i), m / (m / i));
                ans += (LL)(MU[last]-MU[i-1])*D[n/i]*D[m/i];
            }
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    Java的XML解析
    Jackson解析XML
    Eclipse配置MyBatis的xml自动提示【转】
    mui消息框alert,confirm,prompt,toast
    base64编码的作用【转】
    一个mui扩展插件mui.showLoading加载框【转】
    RabbitMQ的使用场景
    Spring集成RabbitMQ
    消息确认机制
    Java操作队列
  • 原文地址:https://www.cnblogs.com/Just--Do--It/p/7326572.html
Copyright © 2011-2022 走看看