zoukankan      html  css  js  c++  java
  • 约数个数求和+线性筛约数——bzoj3994

    这题首先要会线性筛约数个数,并求出前缀和

    bool vis[maxn];
    int mm,mu[maxn],prime[maxn],num[maxn],sum[maxn],d[maxn],sum1[maxn];
    void init(){
        mu[1]=1;num[1]=1;
        for(int i=2;i<maxn;i++){
            if(!vis[i]){
                prime[++mm]=i;
                mu[i]=-1;
                num[i]=2;
                d[i]=1;
            }
            for(int j=1;j<=mm;j++){
                if(prime[j]*i>=maxn)break;
                vis[i*prime[j]]=1;
                if(i%prime[j]==0){
                    mu[i*prime[j]]=0;
                    d[i*prime[j]]=d[i]+1;
                    num[i*prime[j]]=num[i]/(d[i]+1)*(d[i*prime[j]]+1);
                    break;
                }
                else {
                    mu[i*prime[j]]=-mu[i];
                    d[i*prime[j]]=1;
                    num[i*prime[j]]=num[i]*2;
                }
            }
        }
        for(int i=1;i<maxn;i++)sum[i]=sum[i-1]+mu[i];
        for(int i=1;i<maxn;i++)sum1[i]=sum1[i-1]+num[i];
    }
    View Code

    然后通过转化 d(i*j) 化简原式即可

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 500005
    #define ll long long 
    
    bool vis[maxn];
    int mm,mu[maxn],prime[maxn],num[maxn],sum[maxn],d[maxn],sum1[maxn];
    void init(){
        mu[1]=1;num[1]=1;
        for(int i=2;i<maxn;i++){
            if(!vis[i]){
                prime[++mm]=i;
                mu[i]=-1;
                num[i]=2;
                d[i]=1;
            }
            for(int j=1;j<=mm;j++){
                if(prime[j]*i>=maxn)break;
                vis[i*prime[j]]=1;
                if(i%prime[j]==0){
                    mu[i*prime[j]]=0;
                    d[i*prime[j]]=d[i]+1;
                    num[i*prime[j]]=num[i]/(d[i]+1)*(d[i*prime[j]]+1);
                    break;
                }
                else {
                    mu[i*prime[j]]=-mu[i];
                    d[i*prime[j]]=1;
                    num[i*prime[j]]=num[i]*2;
                }
            }
        }
        for(int i=1;i<maxn;i++)sum[i]=sum[i-1]+mu[i];
        for(int i=1;i<maxn;i++)sum1[i]=sum1[i-1]+num[i];
    }
    ll n,m;
    
    inline ll calc(ll n,ll m){return (ll)sum1[n]*sum1[m];}
    
    int main(){
        init();
        int t;cin>>t;
        while(t--){
            cin>>n>>m;
            if(n>m)swap(n,m); 
            ll ans=0;
            for(int l=1,r;l<=n;l=r+1){
                r=min(n/(n/l),m/(m/l));
                ans+=(sum[r]-sum[l-1])*calc(n/l,m/l);
            }    
            cout<<ans<<'
    ';
        }
    }
  • 相关阅读:
    编写一个最原始的Servlet
    windows 通过cmd使用tail命令
    windows 配置jdk8环境变量
    Windows tomcat简单使用
    红黑树
    HashMap源码分析--jdk1.7
    IDEA debug断点调试技巧--转载
    idea 调试的时候变量的值变成了jar包显示
    浅谈Java中的hashcode方法--转载
    家庭记账本之微信小程序(八)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11151879.html
Copyright © 2011-2022 走看看