Sum of a Function(大数区间筛)

本文介绍了一种使用埃式筛法筛选素数的方法,并应用于解决特定数学问题:求解给定范围内最小的k个f函数值之和,其中f函数定义为一个整数的最小素因子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述
Everyone knows that Arup loves prime numbers! This is why he teaches the cryptography course at UCF. Recently, Arup defined the following function on positive integers, n, greater than 1:

f(n) = the smallest prime factor of n

For example, f(14) = 2, f(15) = 3, f(16) = 2 and f(17) = 17.

Using this function, we can generate a sequence of terms f(s), f(s+1), f(s +2), …, f( e), where s designates the starting function input and e designates the ending function input.

Arup thinks these sequences are interesting, but what he’s really curious about is finding the sum of the k minimum elements in one of these sequences. Can you write a program to help him?

Given s, e, and k, find the sum of the k minimum values in the sequence f(s), f(s+1), f(s +2), …, f(e).
输入
The first and only input line will contain three positive integers, s (2 ≤ s ≤ 1018 ), e (s +100 ≤ e ≤ s+106 ), and k (1 ≤ k ≤ 0.9 * (e – s + 1)), representing (respectively) the starting function input, the ending function input, and the number of minimum terms to sum.
输出
On a line by itself, print the sum of the k minimum terms of the designated sequence.
样例输入 Copy
【样例1】
100 200 70
【样例2】
213 419 169
样例输出 Copy
【样例1】
165
【样例2】
546
提示
Even though the input specification does not allow “14 17 3” as an input case (i.e., this case will not be in the judge data), it is a simple case that you may want to use for testing purposes – the output (7) can be verified easily on paper. (BTW, the intended solution should solve this case properly anyway.)

题意

给出你个定义 f i = i 因 数 中 最 小 的 素 数 {f_{i}}=i因数中最小的素数 i=i ,例如  f 14 = 2 f_{14}=2 f14=2 , f 17 = 17 f_{17}=17 f17=17
给出你一个 N N M M M 让我求得 N - M N-M 中最小的 k k f 函 数 值 f函数值 和为多少.

题解

这样的话其实主要任务是筛素数,最大的问题就是这个范围有点大,但是我们发现 M − N M-N MN 最大才1e6了这就让我们想到用埃式筛也就是区间筛来筛这些素数。
注意排序的时候他是从0开始的然后往后数(M-N+1)个数。
也就是

sort(a,a+m-n+1);

其他也就没啥了。就是下面这样

补充

注意看那题中条件 1 ≤ k ≤ 0.9 ∗ ( e – s + 1 ) ) 1≤k≤0.9∗(e–s+1) ) 1k0.9(es+1)) 说明我们不会用到区间内所有的数,只需要前k小的即可,这就意味着我们筛大数的时候就在 1 e 12 − 1 e 18 1e12-1e18 1e121e18中我们利用 1 e 6 1e6 1e6之内的素数没有筛出来那么他要不就是本身是个质数,要不他f值大于 1 e 6 1e6 1e6,而且我们知道素数的密度是越来越大的,所以我们可通过这个条件得知不用筛全区间,我们就可得到结果.

#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
#include <immintrin.h>
#pragma GCC optimize(2)
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<ll,ll> pii;
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
const int maxn=1e6+1010;
#define inf 0x3f3f3f3f
#define sf scanf
#define pf printf
const int mod=998244353;
const int MOD=10007;
 
inline int read() {
    int x=0;
    bool t=false;
    char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
bool isprime[maxn];
ll prime[maxn],dashu[maxn],n,m,k,cnt;
 
void isPrime(int kk){///欧拉筛
    for(int i=2;i<kk;i++)
    {
        if(!isprime[i]) prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<kk;j++)
        {
            isprime[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
}
 
void f(ll l,ll r){
    for(int i=0;i<r-l+1;i++) dashu[i]=i+l;
    for(int i=1;i<=cnt;i++)
    {
        ll s=l/prime[i];
        if(s<=1) s=2;
        for(ll j=s*prime[i];j<=r;j+=prime[i])
        {
            if(j>=l){
                if(dashu[j-l]==j)
                dashu[j-l]=prime[i];    ///因数是prime[i]
            }
        }
    }
 
}
#define read read()
int main(){
    isPrime(maxn);
    cin>>n>>m>>k;
    f(n,m);
    sort(dashu,dashu+m-n+1);
    ll sum=0;
    for(int i=0;i<k;i++){
            sum+=dashu[i];
        //cout<<sum<<endl;
    }
    cout<<sum<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值