1. 程式人生 > >BZOJ-5244 最大真因數(min25篩)

BZOJ-5244 最大真因數(min25篩)

div 給定 ++ col pan bits \n unsigned nbsp

題意:一個數的真因數指不包括其本身的所有因數,給定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; }

BZOJ-5244 最大真因數(min25篩)