Live2d Test Env

BZOJ-5244 最大真因数(min25筛)

题意:一个数的真因数指不包括其本身的所有因数,给定L,R,求这个区间的所有数的最大真因数之和。

思路:min25筛可以求出所有最小因子为p的数的个数,有可以求出最小因子为p的所有数之和。

那么此题就是对于所有素数因子,求它对应的和。

#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long
const int maxn=150010;
ll Sqr,vis[maxn],pri[maxn],sp[maxn],tot,m,id1[maxn],id2[maxn],g[maxn],h[maxn];
ll w[maxn];
void Sieve(int n)
{
    tot=0; vis[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]) pri[++tot]=i,sp[tot]=sp[tot-1]+i;
        for(int j=1;i*pri[j]<=n;j++){
               vis[i*pri[j]]=1;
            if(i%pri[j]==0) break;
        }
    }
}
ll solve(ll n)
{
    Sqr=sqrt(n); Sieve(Sqr); ll res=0; m=0;
    for(ll i=1,j;i<=n;i=j+1){
        j=n/(n/i); w[++m]=n/i;
        if(w[m]<=Sqr) id1[w[m]]=m;
        else id2[n/w[m]]=m;
       if(w[m]&1) g[m]=(w[m]+1)/2*w[m]-1;
       else g[m]=w[m]/2*(w[m]+1)-1;
    }
    for(int j=1;j<=tot;j++)
      for(int i=1;i<=m&&pri[j]*pri[j]<=w[i];i++){
        int k=(w[i]/pri[j]<=Sqr)?id1[w[i]/pri[j]]:id2[n/(w[i]/pri[j])];
        g[i]=g[i]-pri[j]*(g[k]-sp[j-1]);
        if(i==1) res+=g[k]-sp[j-1];
    }
    return res;
}
int main()
{
    ll l,r;
    scanf("%llu%llu",&l,&r);
    printf("%llu\n",solve(r)-solve(l-1));
    return 0;
}

 

posted @ 2019-02-09 20:53  nimphy  阅读(730)  评论(0编辑  收藏  举报