• 【FJWC2018】最大真因数


    题面

    Description

    一个合数的真因数是指这个数不包括其本身的所有因数,

    例如 6 的正因数有1, 2, 3, 6,其中真因数有 1, 2, 3。

    一个合数的最大真因数则是这个数的所有真因数中最大的一个,例如 6 的最大真因数为 3。

    给定正整数 l 和 r,请你求出 l 和 r 之间(包括 l 和 r)所有合数的最大真因数之和。

    Input

    输入共一行,包含两个正整数 l 和 r。保证 l ≤ r。

    Output

    输出共一行,包含一个整数,表示 [l,r] 内所有合数的最大真因数之和。

    Sample Input

    1 10

    Sample Output

    17

    【样例 1 解释】

    在 1 至 10 之间的合数有 4, 6, 8, 9, 10,

    它们的最大真因数分别为 2, 3, 4, 3, 5,

    因此最大真因数之和为 2 + 3 + 4 + 3 + 5 = 17。

    Hint

    【样例 2 输入】

    101 1000

    【样例 2 输出】

    163446

    【样例 3 输入】

    180208 975313

    【样例 3 输出】

    151642139152

    【样例 4 输入】

    339762200 340762189

    【样例 4 输出】

    112318862921546

    【样例 5 输入】

    2500000000 5000000000

    【样例 5 输出】

    3094668961678105770

    img

    题目分析

    要求合数的最大真因数,相当于求合数除以其最小质因子。

    再Min_25筛求素数和的过程中:

    [g(n,j)= egin{cases} g(n,j-1)&P_j^2> n\ g(n,j-1)-f(P_j)cdot[g(frac{n}{P_j},j-1)-sum_{i=1}^{j-1}f(P_i)]&P_j^2leq n end{cases} ]

    其中

    [g(frac{n}{P_j},j-1)-sum_{i=1}^{j-1}f(P_i) ]

    求得的便是最小质因子为(P_j​)的合数之和。

    我们只需在处理(g)的时候统计答案即可。

    代码实现

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #include<iomanip>
    #include<cstdlib>
    #define MAXN 0x7fffffff
    typedef unsigned long long LL;
    const int N=250005;
    using namespace std;
    inline LL Getint(){register LL x=0,g=1;register char ch=getchar();while(!isdigit(ch)){if(ch=='-')g=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}return x*g;}
    int prime[N],tot;bool vis[N];
    LL sqr,w[N],g[N],sp[N];
    int id1[N],id2[N],m;
    void Pre(int n){
    	for(int i=2;i<=n;i++){
    		if(!vis[i])prime[++tot]=i,sp[tot]=sp[tot-1]+i;
    		for(int j=1;j<=tot&&1ll*i*prime[j]<=n;j++){
    			vis[i*prime[j]]=1;
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    
    LL Solve(LL n){
    	tot=m=0;
    	sqr=sqrt(n),Pre(sqr);
    	for(LL i=1,j;i<=n;i=j+1){
    		j=n/(n/i),w[++m]=n/i;
    		g[m]=w[m]*(w[m]+1)/2-1;
    		if(w[m]<=sqr)id1[w[m]]=m;else id2[j]=m;
    	}
    	LL ans=0;
    	for(int j=1;j<=tot;j++){
    		for(int i=1;i<=m&&(LL)prime[j]*prime[j]<=w[i];i++){
    			int k=(w[i]/prime[j]<=sqr)?id1[w[i]/prime[j]]:id2[n/(w[i]/prime[j])];
    			if(i==1)ans+=g[k]-sp[j-1];
    			g[i]-=prime[j]*(g[k]-sp[j-1]);
    		}
    	}
    	return ans;
    }
    int main(){
    	LL l=Getint(),r=Getint();
    	cout<<Solve(r)-Solve(l-1);
    	return 0;
    }
    
  • 相关阅读:
    python命令行工具模块-click
    python项目代码打包成Docker镜像
    背包九讲
    秒杀项目的3个奇数问题:并发队列的选择,请求接口的合理设计,高并发下的数据安全
    java类加载过程
    索引失效
    java面试
    进程间通信
    HashMap在Jdk1.7和1.8中的实现
    十大排序算法
  • 原文地址:https://www.cnblogs.com/Emiya-wjk/p/10458344.html
Copyright © 2020-2023  润新知