这道题需要了解素数筛的原理,而不是只是套模板。
需要明白一点,我们在欧拉筛中筛掉合数用的是这个合数的最小值因子。还记得那一步if(i%primes[j]==0) break;吗?这一步就保证我们用的是最小值因子筛掉所有的合数。
我们可以这么理解,当i%primes[j]的时候,i=k*primes[j],这时候,我们如果不break,继续下一个,则i*primes[j+1]=k*priems[j]*primes[j+1]=(i*primes[j+1])*primes,说明现在的i*primes[j+1]的最小质因子其实是primes[j],只要后面i增大了,i*primes[j+1]自然会被筛掉。
对于这道题,我们只需要改下筛法,记录下最小值因子就行了。
相似题目:CF1047C

AC代码

#include <iostream>
#include <map>
#include <ctime>
#include <vector>
#include <climits>
#include <algorithm>
#include <random>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <bitset> 
#include <queue>
#define inf 0x3f3f3f3f
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define rep(i, a, n) for(register int i = a; i <= n; ++ i)
#define per(i, a, n) for(register int i = n; i >= a; -- i)
#define ONLINE_JUDGE
using namespace std;
typedef long long ll;
const int mod=1e9+7;
template<typename T>void write(T x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
    {
        write(x/10);
    }
    putchar(x%10+'0');
}

template<typename T> void read(T &x)
{
    x = 0;char ch = getchar();ll f = 1;
    while(!isdigit(ch)){if(ch == '-')f*=-1;ch=getchar();}
    while(isdigit(ch)){x = x*10+ch-48;ch=getchar();}x*=f;
}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
ll ksm(ll a,ll n){//看是否要mod 
    ll ans=1;
    while(n){
        if(n&1) ans=(ans*a)%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ans%mod;
}
//==============================================================
const int maxn=3e7+10;
int n;
int primes[maxn],tot;
int vis[maxn];
int fac[maxn];
void init(){
    for(int i=2;i<maxn;i++){
        if(!vis[i]) primes[tot++]=i,fac[i]=i;
        for(int j=0;j<tot&&primes[j]*i<maxn;j++){
            fac[i*primes[j]]=primes[j];
            vis[i*primes[j]]=1;
            if(i%primes[j]==0) break;
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    //===========================================================
    read(n);
    init();
    int ans=0;
    /*rep(i,1,10){
        cerr<<fac[i]<<" ";
    }
    cerr<<endl;*/
    rep(i,1,n) ans+=fac[i]/*,cerr<<fac[i]<<endl*/;
    write(ans);
    //===========================================================
    return 0;
}